All right, welcome back, everybody. And thank you so much for supporting the DEF CON community and especially the Red Team Village. And without any further ado, I pass it back to Gabriel. Take it away. Hi again, everyone. This is a little different, but yeah, this is... I'm introducing a new tool called DropEngine. It's a Malibu payload creation framework. A bit about me, won't go on about this for too long, but my name is Gabe Ryan. I'm a Red Team Operator at Specter Ops. I used to work in a place called Gotham Digital Science doing security consulting. Got my Twitter handle and my LinkedIn username is actually pretty interesting. It's ms08016. So without further ado, let's just dive right into this. Let's talk about initial access payloads. So what are initial access payloads as opposed to normal payloads? Initial access payloads are typically used to gain access to a system environment. So at the very start of your engagement, it's what you're using to essentially gain your initial foothold. They're pretty simple in design. I mean, it really has like one job, which is to execute an implant or second stage payload. And then from there, you pretty much do everything, you know, all your secondary endpoint operations happen from that point onwards. Colloquially, they're also known as droppers or shellcode runners because they run shellcode. But yeah, you know, while initial access payloads do have a pretty simple role, there are some obstacles that you have to face when designing them. So I mean, despite the fact that it's like, you know, they perform a seemingly mundane task, right? That they just load code in memory and execute it. You know, there are some challenges to contend with. The first of which is that, you know, during the delivery phase, so what you're actually trying to get this payload onto the target machine. Usually, that's going to be done via spear phishing. And if that's the direction you're going, you know, this payload is going to be exposed to signature-based detections, you know, in the form of mail filters, you know, and stuff that's scanning through the email that you're sending out. It also may be exposed to automated behavioral analysis. So automated sandboxes, essentially what they do is they take your payload, and they actually execute it in a controlled environment. The reason why they do this is that you know, whereas if you're just looking for signatures, you're going to get these like brittle signatures, but that are kind of easy to evade. But in this instance, if you're looking at that, you know, what the program is doing, while it's executing, you're actually looking at behavior, which is a little more difficult to hide. And finally, during the delivery phase, your payload is going to be downloaded and saved to disk. And you have to do this without triggering AV or, you know, getting caught by EDR or whatever. So that's the final challenge. And then once you've done that, you have to execute your payload. So the payload is going to be executed from disk. Usually if it's like a phishing payload or something like that. Although typically in-memory operations are a little better. You know, when you're just... One of the challenges of your initial access payload is that you can't really start that way. So you have to start from disk a lot of time. And you have to do this without triggering Antivirus or Endpoint Detection and Response, aka EDR. In Windows environments, you know, that you're also going to, you know, application whitelisting is pretty much ubiquitous if you're operating within like an Active Director environment or dealing with Windows. What this means is that you're going to have to find a way to bypass that. And that usually means relying on something called... the concept known as live-off-the-land binaries and scripts or LOBOS. Essentially what these are, I mean, they're just like utilities, they're binaries that become packaged with the operating system. And, you know, they're usually designed to like fulfill some benign role. But you can actually... What makes them special is that they have some functionality that you can essentially leverage to do something that is useful for you as an adversary. So in this case, there are several live-off-the-land binaries and scripts that can be used to execute payloads in various interesting ways. So that's fortunate that you can rely on that. You can use that to bypass application whitelisting. The problem is that most of these pretty much restrict you to programming languages and execution methods that get filtered through the Windows Common Language Runtime or CLR. And CLR, if you're going through the CLR, you have to contend with Microsoft's anti-malware scan interface for AMP-C, which just kind of like examines all this stuff that's going through. So, you know, that's another obstacle you have to do. So in a lot of ways, getting this initial payload working and running can be very challenging, despite the fact that you're trying to do something that's seemingly simple. It's almost paradoxical in that way. And finally, I mean, you should assume that your initial access payload is going to be discovered. That's just a safe assumption to make. So your payload really should be able to withstand manual analysis in the form of threat hunters, reverse engineers, and the like. So with that in mind, all these are obstacles that are insurmountable. There are ways to contend with all of this. It is a bit of a cat and mouse game, but it's something that you can get around. The problem is that successful evasion techniques do not last very long. They have a tendency to get stale. They have relatively short shelf life. And this is because if you're doing your job right, defenders will eventually learn from what you're doing as a red teamer and write detections against whatever TTPs you're using. So those really cool new TTPs that you drop, if you're doing your job right, this will actually improve their security. And they won't work forever if you're using the same TTPs for years and years. Well, you know, you could argue that you're not really improving the security. But yeah, that's a whole other thing. But so defenders will eventually catch up to you. And what this means is that your payloads are finite. They have a shelf life. And that's good. And specific payloads, right? So we were talking about TTPs there, right? But specific payloads that you write have an even shorter shelf life. Because at some point, you know, someone's going to write a signature-based detection for that particular, you know, assembly that you drop on an op or something like that. And, you know, that's relatively easy to do. I mean, relatively, right? I mean, from an adversaries perspective, what this means is that reusing payloads is likely to get you burned. So, you know, this is where... what this means is that initial access payloads are typically, you know, kind of a pain point for offensive teams. And that's because, you know, you have all these challenges that you have to overcome. And the ways that you overcome these obstacles, you know, the methods that you use, essentially, are not going to last. And you typically have to write them by hand, or at least modify them by hand on a per-engagement basis. And, you know, code reuse can be problematic. And there's a lot of moving parts. There's a lot of... I mean, despite the relatively simple purpose, if you've ever looked at, like, the source code for, you know, doing a process hollowing in C-sharp, you'll see there's a lot of code involved. And there's a lot of things that can go wrong. So there's, you know, code reuse is a problem. You have to do a lot of stuff by hand. And there's a lot of moving parts, despite the fact that you're trying to do something relatively simple, which is kind of paradoxical. So to kind of contend with this problem, you know, I was actually just kind of, like, researching payloads independently. But at some point, you know, I just had the idea to work on this new tool called DropEngine. Essentially, the goal of DropEngine is to address this problem by providing a malleable framework for creating shellcode runners. So if you've ever used, like, Coblestrike, for example, one of the cool... one of the things that makes, like, Coblestrike great is the fact that, you know, just about every aspect of your agent that you're placing on... that you're using on the target machines that you're operating on, can be modified. You know, you can modify traffic profiles, you can modify, you know, essentially how it's dealing with, like, you know, using name pipes and whatnot. Like, just about every aspect of its use, you can customize it in some way. And by doing that, you know, really get a lot of use out of this one tool. So I guess the core idea was to try to do something similar with initial access payloads. And, you know, the core idea is to identify discrete payload components so basically, like, examine, you know, like, your typical payload and say, what are all the parts that you see in this payload that kind of repeat themselves across every payload that you ever write? And, you know, identify those and turn them into modules. And as a bonus, provide built-in obfuscation encryption and symbolic substitution capabilities, which makes it easier to evade signature-based detections. And in the case of encryption, makes it easier to, you know, evade human analysts. And, you know, by doing that, we greatly extend the shelf life of, you know, those individual payload components that we're writing. So how would something like this work? To kind of think about this, right, we have to talk about how payloads are built. This is actually, you know, the interesting thing about this project, this is less of a Red Team project than it is like a software development project. Because, like, we're actually not really trying to do a whole lot of crazy stuff here with the actual... ...the payload itself. We're just looking at kind of the abstract design pattern here. You know, if we think about the anatomy of a payload, at their core, initial access payloads are relatively simple. They involve two major steps, which we talked about. You load the shellcode into memory and you execute it. A little bit of terminology I'm going to throw out here. From this point onward in this presentation, we're going to refer to the routine that performs these two actions as the executor function, just to kind of make things simple. So, there are many ways of achieving shellcode execution. You know, you've got the allele injection, spawn a local thread, you use process hollowing, thread execution, hijacking, all kinds of stuff. But we actually want to abstract away specific details like this. We don't really want to focus on them quite yet. Because what we're looking at is actually for more of a bigger picture. You know, also something else we need to consider, we mentioned that we need to... ...contend with application whitelisting. And that really means that we're limited to formats that can be executed by LullBoss, you know, LullBoss for land buyers and scripts. So, what this means is that our initial access payload is really going to require three basic components. And you can kind of see my diagram here on the left here. We're going to have the shellcode runner. Technically, the whole entire thing is a shellcode runner. But we'll, just for the sake of labeling things, you know, we'll refer to this outer wrapper as a shellcode runner. That's going to be LullBoss specific, right? You know, if it's MSBuild payload, that's going to be like an XML file, basically. If it's an installutil payload, that's going to be a C sharp file that's compiled into an assembly. But you have your outer shellcode runner. And then you have your payload name. That's your application entry point. That's going to call your executor function and really everything else that gets called within your payload. But we're not going to worry about everything else yet. It's just these three components. And then finally, you have your executor function. And this is going to load your software to memory, execute it, and, you know, essentially, yeah, that's the meat of this payload so far. So DropEngine implements these basic components as base classes. Essentially, what I've done is I've taken these three components and made it so you can inherit from them and derive modules from them. And what this means is that you can just write a module, and you can use any executor type you want, wrap it in any shellcode runner you want. And the overall structure of the payload remains the same, despite that you have a lot of different options as to how to actually implement all this stuff. To kind of give you an example, you know, we're talking about the structure. You know, this is a... I ripped this direct... Well, there's supposed to be a link to this GitHub, but I guess, like, it's getting cropped on the bottom because it's PowerPoint and Zoom. But yeah, this is from 0x13steveflores' GitHub. It's from a project called MoveKit. This is just an MSBuild runner, right? You have your outer wrapper, which is what we talked about here, right? And this is just your XML file. You have your payload main, which is just importing stuff and calling this executor here. And then you have your actual executor function there, your shellcode inject. So... and this is going to be interesting. I have to switch back and forth here a little bit. I'm actually going to stop sharing for a second and then reshare from Hyper. Cool. So, yeah, you're going to see a lot of other stuff here, but if you look at the overall structure of how things are done, we have our payload main components, have our runners. We can break them into individual discrete components like that. And we'll kind of go into more depth in this in a little bit. And then, of course, we have our executor functions, which I don't have a whole lot of them in there quite yet, but that's okay. So I'm going to stop this in an attempt to share this again. Okay, there we go. And then hit from current slide. Okay. So we've identified our discrete components here, right? These items here. We also want to throw in encryption capabilities. It's typically a good idea to leverage encryption when creating initial access payloads for multiple reasons. Basically, you have your shellcode that is going to be executed by your shellcode runner. A lot of these are going to be like binary payloads or something like that. You don't necessarily want to have to throw that whole entire thing out just because that particular signature is detected by antivirus. What we do is, one way of hiding that from signature-based checks is by encrypting it. But the other advantage of encrypting your shellcode is that it makes it more difficult for human analysts to reverse engineer our payload. Remember, we need to assume that the payload is eventually going to get caught. And when it does, we want to make it as difficult for the reverse engineer to pick this apart as humanly possible. What this means is that our updated payload execution process is actually going to involve a few more steps. We are going to load the encrypted payload into memory. We're going to decrypt that payload using an encryption key to obtain plaintext shellcode. And then finally, we're going to load that plaintext shellcode into memory and execute it. So the extra step here that we've added is this encryption function. If we're going to use encryption, this introduces yet another thing that we have to account for, and that's key storage, derivation, and retrieval. When we leverage encryption to protect our shellcode, essentially this is going to require us to provide our payload with one of the following. It's either going to need to be able to derive the encryption key somehow without actually storing it. So it's not going to store it, but we need to be able to obtain the encryption key somehow. It needs to go... if we can't do that, it could possibly just retrieve the encryption key from some other location. So we could provide it with that capability. Or we could just store the encryption key itself in the payload. Now, obviously, this last option is not ideal because, you know, if you're storing the encryption key in the shellcode, if someone compromised in the payload, then someone compromises the payload, then they can decrypt the shellcode and you're kind of... you're just adding an extra step, but you're not really making it terribly difficult to pick apart. So let's talk about this first option a bit. We mentioned the use of... the first option is to derive the encryption key. One really great way of doing this is the use of environmental keying. This is like a really... I mean, so environmental keying has been around for a pretty long time. I mean, there's a lot, if you just look up like Mauer, you know, environmental keying and just Google it, there's just tons of papers written about the subject. I think that the three most relevant projects to check out though, in terms of like prior work, that's like really relevant to red teaming, would definitely be... well, Ebola is the classic one, you know, that, yeah, that's... so if you look up Ebola GitHub, like that one is going to come up really, and environmental keying, that one will come up. The other one is Spotter, that one was released fairly recently, I think like in 2018 or something like that. And, you know, it pretty much, you know, does something pretty similar. And then also there's... I think like Leo Lupik has some blog posts where he talks about this and also expands off of those. But yeah, so the idea with environmental keying is that you actually derive the encryption key either entirely or in part from values in the environment. So what do we mean by this? Well, I mean, let's say that, you know, by attributes in the environment, you know, we're talking about usernames. So for example, you could use the currently logged in user that your payload is running as, as part of the encryption key. You could, you know, try to obtain the external IP address from where your payload is executing and use that as part of the encryption key. You could, you know, use your... make sure that you're actually on the right computer by deriving the encryption key in part by using your internal FQDN. I actually didn't like... you could even like use the moon phase or something like that. I mean, you can, you know, but essentially what this lets you do... well, there's two things. One, it makes your payload very, very resistant to analysis because your encryption key is now no longer being stored in the payload. And essentially they'd have to, you know, essentially like if you're setting encryption key to the value of the hard drive serial number, you know, that means that you'll be able to decrypt and execute your payload on a specific machine that has that particular hard drive plugged in. But if you're an analyst and you just have a copy of this payload, unless you know what specific machine you're going after and what the serial number is, you're essentially forced to attempt to crack that encryption by guessing the value of that serial number. So it makes your payload super hard to crack. And the added advantage is that it's very targeted. Your shellcode is only going to be decrypted on machines that match the key's specific attributes or if someone says they're brute forcing for a very, very long time. So I'm now going to set the first live demo of this. Over Zoom, no less. All right. So I'm going to do a couple of things. First, I'm going to show you my setup that I'm using for this, because I think that's important, just so you all know kind of what's going on here. So I'm going to stop sharing for one second and I'm literally going to share. Well, can I do that? Okay, actually, yeah. So the first thing I have to show you, security settings on this machine that I'm using, because that's actually very relevant. And you should see it. Okay, let me try sharing this again. Oh, you know what I can do? Yeah, here it is. Okay, I got it. So as you can see, I don't have cloud delivery protection because I don't want the stuff I'm working on at the moment to get shipped off to antivirus analysis land, essentially. So that's turned off, as well as automatic sample submission. But this is a brand new Windows 10 install. I have real-time protection turned on. Tamper protection is turned on, so you can't disable it. But I do have an exclusion setup, and I want to explain this really fast in case you're wondering why certain things aren't working. So I have one exclusion here, and this is this directory, demo AB include. So essentially, what I'm going to be doing during these demos is I have four, and I'm going to have to now switch windows that I'm sharing again. So you should see hyper right now. There's four terminals. I'm going to try to make this a little cleaner. So in the top left, this is just for my benefit. That's essentially, I'm trying not to anger the demo gods. So I am keeping as much of this stuff in the text file, and I'm going to run the commands that are in there rather than trying to just guess. This will be relevant later. This is going to be a remote key server, and you can kind of... we'll talk about that in a second. This is a Metasploit instance. So this is... yeah, so we're actually going to use Meterpreter for this. So every AV engine under the sun should be able to detect what we're doing, essentially, is what I'm trying to say. We're just using... the payload we're going to be using is going to be just a plain Meterpreter reverse HTTPS. We have to use HTTPS because the actual unencrypted traffic will be picked up immediately. So that exclusion that we're seeing... I'm just being difficult. I'm going to have to... It's going to be in this directory here. I'm going to AV exclude. And this is because we're going to be building this payload, and although the payload was generated here, the second I SCP that payload over onto my main machine, which is what you're seeing in this top right terminal here, Defender would just nuke that. And I really don't want to just keep turning Defender on and off every time I have to do a demo, which is because that's just going to... I'm trying to make this go as smoothly as possible. So the compromise here is that we're going to be pulling our actual shellcode out of demo AV exclude. But when we execute it, that's not where we're executing from. We're going to be executing outside of that exclusion folder. Okay, with that out of the way, let's show you how to go over... Let's go over how we'd make a payload using environmental keying. So essentially, the first thing we're going to do is get a list of available models, right? And just run this. And these are all the different payload components we can choose from. So let's say that we want to use environmental keying. We want to essentially grab... Let's do the FQDN, because I have that written down, and my current username. So we're going to derive the key from that. In that case, we could just do this. We could do Python, prop engine, break onto a new line here, specify that our shellcode should be... You know, in that demo, maybe exclude to shell. We're going to use an interface... So the interface, I'm specifying this command interface. That's like literally the glue that holds everything together. You know, if you're working in C-sharp, you're going to use a C-sharp interface. Don't worry about that too much. But we're going to say, C-sharp runner interface, right? And then we're going to also look at... Just like this encryption key. We need an encryption key and a decryption key. So the EQ keys we're going to use are going to be this external FQDN that we talked about. And notice I'm using more than one. We'll kind of go into how that works in a second, right? I'm just going to use the decryption keys, which is essentially these things, but written in C-sharp. I'm just going to copy these, put them in there. We're then going to need to select a encryptor. It's doing encryptor shellcode. So we're going to say, encryptor AES. We're just going to use AES-256. That should really be named AES-256, not just AES. I should change that. And we're going to use a decryptor. So decryptor C-sharp, origin doll AES, which is the corresponding decryption function that we need. Finally, for our shellcode, we'll go ahead and use msbuild, because that will save you from having to compile something, which will take extra time. And then we're going to need a mutator. We haven't really talked about mutators yet, but we will. But for now, I'm going to say mutator string. And essentially, what that's going to do, it's going to take all the variable names in our finished output and change them to a random string. So it just makes it a little harder to signature around. And that really is... Oh, we also need to specify the actual username and external FQDN that we're trying to use for our key. So I'll put my username as FQDN. And I'm just going to copy it from here. And hopefully, this is an update in the last time, like in the past hour or so. I don't think it would have. And finally, oops, I forgot something. We need an executor function. Yeah, so we need that executor function that actually executes our shellcode. And we're just going to use C-sharp virtual alloc thread. And so you may call it virtual alloc, virtual protect, and all that. And we're going to make our output file example.csproj. And that's going to be our MSBuild file. Cool. Looks like it ran. Didn't get any errors. If you look at our example.csproj, here is an obfuscated MSBuild file. Actually, I should probably show you what this is actually doing. I'm going to do mutate or null, which basically means don't mutate anything. But yeah, so basically, here are all the different components that are stacked together. Here are your decryption keys, and your decryptor, and your executor, and everything else. And then here's your actual payload itself and payload name. Essentially, all this is just being rendered into the payload by DropEngine. Automagically. And finally, I run everything down there. But I want this to be random, because I don't know. Demo gots, I guess. So I made that a random one. So now we're going to set up our handler. Use exploit multihandler payload for CTP. Lhost set Lport 443, which should be correct. And I'm going to set exploit-j to start our handler in the background. And then we're going to actually run this using AliceBuild. And there we go. Now, just to kind of, in case you don't believe me, that this is actually doing something. I'm going to kill everything here. That was a bad sign. But I copy of the enter nano. All right. You know what? I'm actually deviating from the demo right now. And I think that's a bad idea. We'll get back to this if we have time. No, actually, you know what? I'm stubborn. Let's do the... Yeah, I copy demo AV exclude empty shell. And let's just copy it up on level. We should get alert. Or perhaps not. Maybe we might have to run it to get the alert. But yeah, I'm not going to say you're tinkering with this. Let's get back to PowerPoint. OK. From current slide. So that's our payload. Basically, custom build payload with environmental keying that we literally just created in a second. So mutator modules, right? We mentioned also that we're using... Ignore me. I could have sworn there was something else that I was supposed to talk about there. OK. Yeah. So the other thing, essentially what we've just done. We've said, here's the executor function we want to use. Here's the shellcode runner we want to use. Here's the encryption decryption routines we want to use. And by the way, we want to derive our keys from these two specific functions. And we're going to pull this stuff together and make it into a payload. And by the way, randomize all the variables in variable names in that payload. And just write a command, and then it just does it. And then voila, you have a payload. The way that we did the actual... The changing of the variable names was using basically modular symbolic mutation. So DropEngine supports the use of mutator modules that... I mean, essentially what they do is that they... Every module that corresponds to something that has variable names or function names has a mutator method that gets called in the back end by whatever mutator module that you select. And the mutator module then systematically goes through and takes a list of variable names and maps them using some algorithm. The algorithm is irrelevant. It's module specific. And then when the actual... And returns back to that module, the original module, that mapping. So like a dictionary of like, here's all your variable names, and here's the stuff that we've mapped them to. And then what happens is that when you render... When that module gets rendered into a rendered template, and that's how we're building everything. It's using Jinja templates. We are... Essentially what's going on is that it looks at that mapping in order to figure out what's in the variable. So this is pretty cool because it allows us to create payloads that, you know, circumvent signature-based detections pretty easily. I only have like three supported methods in there right now. Rot13, the random string, and also symbol substitution using a word list. Null mutator doesn't really count because that's just... It just doesn't do anything. It's a null mutator. It's primarily there for debugging purposes. And I've kind of already demonstrated that, but if you want to just go over... Just once again, what that looks like. You know, take this one that we just did, just print to the screen instead of out the file. So for example, here's your... Actually, let me use... I've got another piece of shellcode that isn't so long that we can use for demos. Yeah, so, you know, here's your random strings. You know, if you wanted to use... Rot13. These look an awful lot like the variable names. Let's use a word list. You actually have to specify a word list when you do this. Let's use US cities. And that will... Now all your variable names are corresponding to US cities. A better use of this would just be to make a word list that actually are believable variable names. But I don't know, this is better for doing a demo. Let me go back to PowerPoint. Let's move on from here. And let me just make sure... Okay, cool. So let's talk about some more keying techniques that we support. We talked about environmental keying. Remote keying is also pretty neat. Essentially, instead of deriving the key from some place in your environment, you're actually going to retrieve the encryption key from some remote location, you know, either for HTTP or HTTPS, DNS, or some other communication protocol. This is actually... You know, if you have well-designed non-attributable attack infrastructure, it actually makes this method pretty effective. You know, you can place the key server behind a redirector and only accept requests for that key on very specific... for very specific profile traffic that's being sent to the redirector. If you want to make it even better, you can use a one-time remote key, which is a variant in which your key server, which is the server that's hosting these remote keys... By the way, you want to have one key per payload, and DropEngine does support that. So keys should be unique to the payload that you generate. But essentially, the one-time remote key variant, once that key is successfully retrieved from the key server, it actually is deleted from the key server. So the key server goes back into its database and just nukes the key. And what this means is that any future requests for that key are either going to be ignored by the key server, or return some kind of junk data, or you could even, at that point, respond to that kind of request by returning a redirect. So you could do what a redirect would do and redirect that request to something innocuous, like, you know, remotely hosted jQuery or something. Like, look, it's not... it's just jQuery, right? But so, I mean, there are obviously some obvious advantages to doing keying this way. It's very resistant to analysis. The encryption key is not stored on the payload file. And it's hopefully being protected in transit using TLS. It's also less targeted, right? You know, while highly targeted payloads are good in a lot of cases, sometimes they're not. Sometimes you don't just want to attack the computer of that one person that has that particular hard drive or username. Sometimes you want a little more breadth. In this case, you don't have to limit your scope. I mean, you should limit your scope regardless. But I guess what I'm saying is the scope isn't, you know, implicitly limited by your keying mechanism at this point. So I'll show you how this works in Dropbox really fast. And I'm going to go back to my screen here, go back to Hyper. And so in the bottom left, we have this, what looks like a Flask app. It's really, really basic. I honestly didn't put a whole lot of time into this because, you know, I was just trying to get the proof of concept out the door. But this is our remote one-time key server. And what we're going to do here is do a very similar payload to what we just did, right? Hang on, let me... So we're going to grab this. And this is, you know, as you can see here, well, it's just RAM. But what we just did, we created a shellcode using our empty shell, like our interpreter shell that's in that empty shell.bin file. It's pretty much the same attributes we used last time. The difference here is we actually added some keying components. We added a new key here, which you can see right here. It's the D-key one-time remote HTTP and the corresponding decryption key, which is their D-key remote C-sharp OTK HTTP. And essentially what this is doing is it's just providing functions that will attempt to reach out to this server right here that is running at the bottom left to retrieve this encryption key. And it's going to use that by using a specific identifier that you need to your implant. So that, you know, essentially what this guy down here is going to do is look in the database to see if that identifier exists. And if it does, it's going to respond with the decryption key and send it back to our payload. And then, you know, it'll be deleted from the database. So subsequent requests just won't be honored. So let's run that really fast. We just kind of prep the bottom left here. Make sure we don't have any stragglers either in our sessions or... Oh, okay, cool. So we're going to run our handler. And we're going to rebuild this really fast just to make sure everything looks selfless enough. It does. And we're going to call it MSBuild once again. And there we go. And you'll notice here, this traffic showed up in the Flask app. And that is our server going back. That's our payload retrieving the key, right? Now, let's go ahead and kill this session right here, right? And the reason why I'm doing that is I want to show you what happens when we... So we've already retrieved that remote key. So what we're going to do now is we're going to just kind of demonstrate. If we happen to curl for that same value, right? Let's say we do a curl request to 127. This is running on mobile, so we can just do this. HTTP//, we're not using SSL at the moment. Oh, you know what? We'd actually need the implant ID, wouldn't we? Oh, no, here it is. Yeah, let's grab this implant ID right from here. Cool. So we have everything we need to make this work. And you'll see that we don't actually get a response at this time because it's been cleared. All right, so back to our PowerPoint. We've got about 20 minutes left. Open this up for chat for about 10. Let's go back here. Press slide. All right. So one thing you'll notice is that we're actually using multiple encryption keys here. Or it seems like it, right? Because we're specifying these different key types and combining them to create a final encryption key. We're doing this using something that I like to call key stacking. Key stacking is just like a label. I'm sure this has been done before a million times because it's really not that complicated. It's pretty simple in practice. And we'll see that in a minute. But essentially key stacking is the practice of combining the results of multiple keying methods to create a single combined keys. So for example, let's say we want a key that's combined of four parts. The hard drive serial number, external IP address, a non-stored in the payload file, so it's a stored component, and also a one-time key that is retrieved over HTTPS. Well, in that point, we essentially would just make four method calls within our payload. To four different key derivation functions, concatenate the results together. And by doing that, we'd have one encryption key that was derived from all these different sources. So one advantage of doing this is it gives us a little more security. It's difficult to compromise. Disadvantage is kind of complicated. If you do this by hand, it's just adding more moving parts to the equation. But once again, since we're using a framework, it makes it a little less complicated. Essentially, what makes this possible is that the actual architecture that we saw at the very beginning, it has been updated a little bit. So remember, originally, we just had that shellcode runner and a payload main in there and an executor function. In this case, we still have our shellcode runner. It's our outermost wrapper. That's our LulzBot-specific script that encapsulates everything. But we also have our payload main. And within that, we now have, you see here, we all have all these D-key functions. So we have a D-key 1, D-key 2, all the way through D-key N. It's an arbitrary number of D-key functions. And essentially, the way that this works is that each key part is extracted from each of these key derivation functions and passed to the decryptor function along with the shellcode that combined or stacks keys is then used to get the plaintext shellcode and is passed to the executor. So really, it's not too bad. We already went over key stacking. So let's talk about pre-modules and post-modules. And I included the cookie monster here, because who doesn't like the cookie monster? So what are pre-modules and post-modules? Essentially, this is a concept. I mean, there's often when you're executing that initial access payload, right, that shellcode within your shellcode runner, there are things that you want to do first before you actually start trying to execute your shellcode. For one thing, you might want to perform sandbox checks, like if you're trying to see if you're in one of those automated sandboxes, you might want to check for some node attributes of the sandboxes, such as certain file paths or number of CPUs or what have you, to actually see if you're in a quote-unquote real environment or in a sandbox. Also, we mentioned that this is likely going to be going through the CLR. So you might want to try to bypass AMSI, and that's something that you might want to try to do before you execute your shellcode. So what pre-modules do, essentially, they are just subroutines that are pre-pended to everything else in your payload. So what DropEngine lets you do is you can specify any number of pre-modules that you want, and these will just get run before everything else does. So, for example, if you want to run a sandbox check and an AMSI bypass, you pass those both to DropEngine as pre-modules, they then get executed, and then once they finish executing, and they are executed in the order that you specify them, by the way, which is pretty cool because you actually control which order they execute in. But once they finish executing, then we execute the rest of your shellcode here. So post-modules, they're pretty much the opposite thing. Instead of being pre-pended to the beginning of the payload, we append them to the end of the payload. So that's useful for if there's something that you want to do after your shellcode terminates. So cleanup routines, log file deletion, modification, and both pre-modules and post-modules should be completely modular and mutable, just like the rest of the payload's components. So you can mangle all the string names and variable names, however you want. And so if we're going to demo the process of adding pre-modules, here's how you do it. I'll make this a super fast one. So for example, here, you can see if we want to create a payload that, let's say we want to run an empty sandbox check, say like check to see if we're in a sandbox by checking the minimum number of USBs that have ever been installed. Let's say we look for also file paths that can deliver us to the event that we're in a sandbox. A file path is a sandbox check. Then finally, we want to execute an empty scan buffer bypass. We can just append these here as pre-modules. And actually, if you're curious what this looks like, I'm not actually going to save this. I'm just going to send it to the screen. Yeah, that's what I want to do. And then I'm going to use that really, really small shellcode that I showed you earlier. It's easier to read. It should not be from the exclusion folder, because that small shellcode is not in the exclusion folder. And you'll see here that, you know, here are your sandbox checks and your empty bypass, and that's all getting executed up here, essentially. So that all gets done right before you run everything else. So once again, let's get up on our MSVL payload. We're going to start up our handler, and we created it in the last step, so I'm not going to recreate it. And you see that it runs, so everything just kind of goes swimmingly, because we're out of the sandbox. We go ahead and fill this... PowerPoint, just wrap this up. We kind of did both demos at once, and that's all right. The last thing we're going to talk about is, essentially, how do you create DropEngine modules? So the goal of the project isn't really to provide pre-baked methods for bypassing APADDR. It's really more... We did provide some example modules, but really, they're not really doing anything new or novel. And this is by design, because the goal of this framework is to enable red teams to maximize the value that they get from their individual payloads by converting them into reusable modules. And if you're a defender, this is useful, too, because you can use this tool to quickly create large sets of sample payloads from which to build a learning strategy. So there are two types of modules that you can build, input modules and output modules. Essentially, input modules are anything that's going in before it hits your payload. So your encryption function is an input module, whereas, for example, your executor function is going to be an output module. This is super important. Shout out to Marcelo, my leader, because basically the loader that he's using to build these is heavily based off of some of the stuff he's done. When I think about input modules, they always have to correspond to one or more matching output modules. But they're relatively simple to implement. As you can see here, what we're doing is we're building an encryption key module. And we're just inheriting from this base class and then creating a constructor, which is just kind of setting the various attributes associated with this. All the argument handling is up on the back end. If you want to pass command line arguments to your module, you just add an add arguments function. If you've ever used parse in Python before, you can just add all these here. The parser is already initialized by one of the parent classes of your module. So you can just make calls to self.parse.addArgument and add all the arguments you want. And that will get parsed automatically, essentially, once your payload is generated. And then you have your generate routine. And this is essentially... Well, for encryption keys, it's generate, but depending on the module type you're using, you're going to have your function that actually does stuff. Output modules, very similar, but even simpler. So the way the output modules work, this is the actual... These actually get rendered into your payload. They may potentially correspond to an input module. They may not, as in the case of an executor, for example. But it's really just a simple two-component design. You have a Jinja template and a Python file that stores metadata that is passed to the Jinja template. So, for example, here I've got a list of all my variables and imports and whatnot. And that gets passed to the interface, then passed back, and then loaded into the template in however format you need it. And then here you just have the Jinja template that you're using. As far as actually creating these things go, how much time do we actually have? I won't spend too much time on this. And it's just that if you want to create one of these modules, aside from the stuff... I guess what we haven't really shown you is the template. But here's just an example module. It doesn't really do anything. But see, all that you have to do is just set these attributes, and then you give it a list of interfaces it's compatible with, and then any input modules it's compatible with. Give it a list of all the variables in your C-sharp file, or whatever kind of file you're using. Really, it's not limited to C-sharp. And then also give it the name of a template, and give it a function and class name. In this particular instance, you have to do that. It's not very long. Then you have to create a template. And so, literally, this is the process of creating a template. And I'm actually working on automating this. But that requires, essentially, you need to write something that can parse C-sharp. And that's coming along, but it's not quite done yet. But for now, what you do, if you want to actually turn just a normal C-sharp file into a template that can be understood by DropEngine, you just find all your variables in here, and just wrap them in this Jinja parameter. So you just say d, and then you use a syntax here. So we've got variable nick. We just kind of edit it like that. And then we can do the same thing here with variable n. It should be our only two variables there. And I just do that once again over here. This is going to be painful for longer ones, but, you know, you only have to do it once in that case. And I'm working on some ways to kind of automate a lot of that. Share screen... Back to PowerPoint... And that's pretty much it. I'm going to... Actually, this is a Zoom thing, so I don't really know. That's the location of the project on GitHub, if you want to check it out. I'm going to... I think it's supposed to be like a Q&A thing right now, and I need to figure out how that works. So I'm going to... Yeah, basically, once again, thank you so much for your time and for the presentation here. Excellent presentation. So for the Q&A, you can jump into Discord. It's going to be offline, of course. There's a little bit of delay between the stream and when they can answer. And there's a lot of people actually already talking about the presentation. So kudos. And for those of you also that probably just joined, please take a look at all the talks and all the activities that we have in our website. The description should be in the bottom of the screen, right? So in the description of the screen, all the links and related material. And also, please join the conversation, as we said, in Discord. So we're going to go in a little break, and the next presentation will start in just a few minutes. Thank you again, Gabriel.