[00:00.580 --> 00:02.400] All right, welcome back, everybody. [00:02.400 --> 00:06.400] And thank you so much for supporting the DEF CON community [00:06.400 --> 00:08.740] and especially the Red Team Village. [00:08.760 --> 00:12.080] And without any further ado, I pass it back to Gabriel. [00:12.460 --> 00:13.480] Take it away. [00:14.080 --> 00:15.180] Hi again, everyone. [00:15.580 --> 00:20.240] This is a little different, but yeah, this is... [00:20.240 --> 00:22.660] I'm introducing a new tool called DropEngine. [00:22.660 --> 00:25.460] It's a Malibu payload creation framework. [00:25.480 --> 00:29.000] A bit about me, won't go on about this for too long, [00:29.000 --> 00:30.420] but my name is Gabe Ryan. [00:30.420 --> 00:32.580] I'm a Red Team Operator at Specter Ops. [00:32.700 --> 00:34.700] I used to work in a place called Gotham Digital Science [00:34.700 --> 00:36.820] doing security consulting. [00:37.240 --> 00:41.520] Got my Twitter handle and my LinkedIn username [00:41.520 --> 00:42.480] is actually pretty interesting. [00:42.480 --> 00:45.640] It's ms08016. [00:46.620 --> 00:49.740] So without further ado, let's just dive right into this. [00:50.060 --> 00:52.540] Let's talk about initial access payloads. [00:52.580 --> 00:54.460] So what are initial access payloads [00:54.460 --> 00:55.760] as opposed to normal payloads? [00:55.760 --> 00:57.720] Initial access payloads are typically used [00:57.720 --> 01:00.060] to gain access to a system environment. [01:00.060 --> 01:02.280] So at the very start of your engagement, [01:02.280 --> 01:07.020] it's what you're using to essentially gain your initial foothold. [01:07.880 --> 01:09.260] They're pretty simple in design. [01:09.260 --> 01:10.760] I mean, it really has like one job, [01:10.760 --> 01:13.540] which is to execute an implant or second stage payload. [01:13.820 --> 01:16.140] And then from there, you pretty much do everything, [01:16.140 --> 01:18.460] you know, all your secondary endpoint operations [01:18.460 --> 01:20.160] happen from that point onwards. [01:20.520 --> 01:23.580] Colloquially, they're also known as droppers or shellcode runners [01:24.200 --> 01:25.560] because they run shellcode. [01:27.320 --> 01:29.800] But yeah, you know, while initial access payloads [01:29.800 --> 01:31.980] do have a pretty simple role, [01:31.980 --> 01:36.100] there are some obstacles that you have to face when designing them. [01:36.100 --> 01:38.720] So I mean, despite the fact that it's like, [01:38.720 --> 01:40.780] you know, they perform a seemingly mundane task, right? [01:40.780 --> 01:43.120] That they just load code in memory and execute it. [01:43.740 --> 01:45.840] You know, there are some challenges to contend with. [01:45.840 --> 01:49.100] The first of which is that, you know, during the delivery phase, [01:49.100 --> 01:50.700] so what you're actually trying to get this payload [01:51.740 --> 01:53.460] onto the target machine. [01:53.900 --> 01:56.560] Usually, that's going to be done via spear phishing. [01:56.600 --> 01:59.000] And if that's the direction you're going, [01:59.000 --> 02:03.040] you know, this payload is going to be exposed to signature-based detections, [02:03.040 --> 02:04.360] you know, in the form of mail filters, [02:04.360 --> 02:08.860] you know, and stuff that's scanning through the email that you're sending out. [02:09.080 --> 02:12.020] It also may be exposed to automated behavioral analysis. [02:12.020 --> 02:14.700] So automated sandboxes, essentially what they do [02:16.080 --> 02:17.580] is they take your payload, [02:17.580 --> 02:21.020] and they actually execute it in a controlled environment. [02:21.220 --> 02:23.140] The reason why they do this is that [02:24.620 --> 02:27.240] you know, whereas if you're just looking for signatures, [02:28.040 --> 02:29.800] you're going to get these like brittle signatures, [02:29.800 --> 02:31.840] but that are kind of easy to evade. [02:31.840 --> 02:33.780] But in this instance, if you're looking at [02:34.500 --> 02:36.860] that, you know, what the program is doing, [02:36.860 --> 02:38.240] while it's executing, [02:38.240 --> 02:40.420] you're actually looking at behavior, [02:40.420 --> 02:42.580] which is a little more difficult to hide. [02:43.860 --> 02:45.520] And finally, during the delivery phase, [02:45.520 --> 02:47.680] your payload is going to be downloaded and saved to disk. [02:47.680 --> 02:48.900] And you have to do this without triggering AV [02:48.900 --> 02:51.220] or, you know, getting caught by EDR or whatever. [02:52.580 --> 02:55.300] So that's the final challenge. [02:55.380 --> 02:56.520] And then once you've done that, [02:56.520 --> 02:57.720] you have to execute your payload. [02:57.720 --> 03:00.260] So the payload is going to be executed from disk. [03:00.280 --> 03:05.280] Usually if it's like a phishing payload or something like that. [03:05.820 --> 03:10.060] Although typically in-memory operations are a little better. [03:10.520 --> 03:11.680] You know, when you're just... [03:12.440 --> 03:13.920] One of the challenges of your initial access payload [03:13.920 --> 03:15.920] is that you can't really start that way. [03:15.920 --> 03:18.140] So you have to start from disk a lot of time. [03:19.280 --> 03:21.220] And you have to do this without triggering Antivirus [03:21.220 --> 03:24.320] or Endpoint Detection and Response, aka EDR. [03:24.520 --> 03:26.920] In Windows environments, you know, [03:26.920 --> 03:28.180] that you're also going to, you know, [03:28.180 --> 03:30.600] application whitelisting is pretty much ubiquitous [03:31.110 --> 03:33.100] if you're operating within like an Active Director environment [03:33.100 --> 03:34.760] or dealing with Windows. [03:35.800 --> 03:38.860] What this means is that you're going to have to find a way to bypass that. [03:38.860 --> 03:41.380] And that usually means relying on something called... [03:41.380 --> 03:46.620] the concept known as live-off-the-land binaries and scripts or LOBOS. [03:46.680 --> 03:47.860] Essentially what these are, [03:47.860 --> 03:49.240] I mean, they're just like utilities, [03:49.240 --> 03:54.000] they're binaries that become packaged with the operating system. [03:54.380 --> 04:00.160] And, you know, they're usually designed to like fulfill some benign role. [04:00.220 --> 04:01.880] But you can actually... [04:01.880 --> 04:04.560] What makes them special is that they have some functionality [04:04.560 --> 04:07.460] that you can essentially leverage [04:07.460 --> 04:10.740] to do something that is useful for you as an adversary. [04:10.740 --> 04:14.560] So in this case, there are several live-off-the-land binaries and scripts [04:14.560 --> 04:21.520] that can be used to execute payloads in various interesting ways. [04:22.140 --> 04:23.920] So that's fortunate that you can rely on that. [04:23.920 --> 04:27.680] You can use that to bypass application whitelisting. [04:27.680 --> 04:32.200] The problem is that most of these pretty much restrict you to [04:34.440 --> 04:36.400] programming languages and execution methods [04:36.400 --> 04:40.540] that get filtered through the Windows Common Language Runtime or CLR. [04:40.540 --> 04:42.340] And CLR, if you're going through the CLR, [04:42.340 --> 04:47.100] you have to contend with Microsoft's anti-malware scan interface for AMP-C, [04:47.100 --> 04:49.520] which just kind of like examines all this stuff that's going through. [04:49.880 --> 04:53.640] So, you know, that's another obstacle you have to do. [04:53.640 --> 04:57.580] So in a lot of ways, getting this initial payload working and running [04:57.580 --> 04:58.760] can be very challenging, [04:58.760 --> 05:03.500] despite the fact that you're trying to do something that's seemingly simple. [05:04.360 --> 05:06.320] It's almost paradoxical in that way. [05:08.660 --> 05:11.260] And finally, I mean, you should assume [05:11.260 --> 05:13.380] that your initial access payload is going to be discovered. [05:13.500 --> 05:15.740] That's just a safe assumption to make. [05:16.060 --> 05:18.800] So your payload really should be able to withstand manual analysis [05:18.800 --> 05:21.680] in the form of threat hunters, reverse engineers, and the like. [05:23.660 --> 05:28.620] So with that in mind, all these are obstacles that are insurmountable. [05:28.660 --> 05:31.240] There are ways to contend with all of this. [05:31.620 --> 05:37.300] It is a bit of a cat and mouse game, but it's something that you can get around. [05:37.360 --> 05:41.240] The problem is that successful evasion techniques do not last very long. [05:41.260 --> 05:43.600] They have a tendency to get stale. [05:43.600 --> 05:46.360] They have relatively short shelf life. [05:46.380 --> 05:48.560] And this is because if you're doing your job right, [05:48.560 --> 05:52.800] defenders will eventually learn from what you're doing as a red teamer [05:52.800 --> 05:58.020] and write detections against whatever TTPs you're using. [05:58.020 --> 06:03.420] So those really cool new TTPs that you drop, [06:03.420 --> 06:06.080] if you're doing your job right, this will actually improve their security. [06:06.080 --> 06:11.240] And they won't work forever if you're using the same TTPs for years and years. [06:11.260 --> 06:15.880] Well, you know, you could argue that you're not really improving the security. [06:15.880 --> 06:17.360] But yeah, that's a whole other thing. [06:17.360 --> 06:20.340] But so defenders will eventually catch up to you. [06:20.340 --> 06:23.980] And what this means is that your payloads are finite. [06:23.980 --> 06:26.360] They have a shelf life. [06:26.820 --> 06:28.220] And that's good. [06:28.300 --> 06:30.020] And specific payloads, right? [06:30.020 --> 06:31.720] So we were talking about TTPs there, right? [06:31.720 --> 06:35.500] But specific payloads that you write have an even shorter shelf life. [06:35.500 --> 06:38.860] Because at some point, you know, [06:39.460 --> 06:42.200] someone's going to write a signature-based detection for that particular, [06:42.700 --> 06:46.420] you know, assembly that you drop on an op or something like that. [06:46.640 --> 06:50.120] And, you know, that's relatively easy to do. [06:50.120 --> 06:51.820] I mean, relatively, right? [06:51.820 --> 06:54.080] I mean, from an adversaries perspective, [06:54.080 --> 06:57.300] what this means is that reusing payloads is likely to get you burned. [06:57.300 --> 06:59.440] So, you know, this is where... [06:59.440 --> 07:03.000] what this means is that initial access payloads are typically, [07:03.000 --> 07:05.840] you know, kind of a pain point for offensive teams. [07:06.700 --> 07:08.780] And that's because, you know, [07:08.780 --> 07:10.980] you have all these challenges that you have to overcome. [07:11.280 --> 07:15.160] And the ways that you overcome these obstacles, [07:16.160 --> 07:19.100] you know, the methods that you use, essentially, [07:20.640 --> 07:22.040] are not going to last. [07:22.040 --> 07:23.540] And you typically have to write them by hand, [07:23.540 --> 07:28.660] or at least modify them by hand on a per-engagement basis. [07:29.080 --> 07:31.860] And, you know, code reuse can be problematic. [07:32.340 --> 07:33.700] And there's a lot of moving parts. [07:33.700 --> 07:35.280] There's a lot of... [07:35.280 --> 07:37.440] I mean, despite the relatively simple purpose, [07:37.440 --> 07:40.260] if you've ever looked at, like, the source code for, you know, [07:40.260 --> 07:42.140] doing a process hollowing in C-sharp, [07:42.140 --> 07:43.880] you'll see there's a lot of code involved. [07:43.880 --> 07:46.620] And there's a lot of things that can go wrong. [07:47.300 --> 07:50.280] So there's, you know, code reuse is a problem. [07:50.460 --> 07:52.600] You have to do a lot of stuff by hand. [07:52.600 --> 07:53.580] And there's a lot of moving parts, [07:53.580 --> 07:55.680] despite the fact that you're trying to do something relatively simple, [07:55.680 --> 07:57.240] which is kind of paradoxical. [07:59.080 --> 08:00.860] So to kind of contend with this problem, [08:00.860 --> 08:03.200] you know, I was actually just kind of, like, [08:03.200 --> 08:04.440] researching payloads independently. [08:04.440 --> 08:05.740] But at some point, you know, [08:05.740 --> 08:09.300] I just had the idea to work on this new tool called DropEngine. [08:09.300 --> 08:12.540] Essentially, the goal of DropEngine is to address this problem [08:12.540 --> 08:17.660] by providing a malleable framework for creating shellcode runners. [08:17.880 --> 08:20.880] So if you've ever used, like, Coblestrike, for example, [08:20.880 --> 08:21.660] one of the cool... [08:21.660 --> 08:23.340] one of the things that makes, like, Coblestrike great [08:23.340 --> 08:27.580] is the fact that, you know, just about every aspect of your agent [08:27.580 --> 08:29.220] that you're placing on... [08:29.220 --> 08:33.100] that you're using on the target machines that you're operating on, [08:34.440 --> 08:35.380] can be modified. [08:35.380 --> 08:36.840] You know, you can modify traffic profiles, [08:36.840 --> 08:42.240] you can modify, you know, essentially how it's dealing with, like, [08:42.240 --> 08:43.980] you know, using name pipes and whatnot. [08:44.100 --> 08:47.140] Like, just about every aspect of its use, [08:47.140 --> 08:49.420] you can customize it in some way. [08:49.420 --> 08:51.660] And by doing that, you know, [08:51.660 --> 08:54.240] really get a lot of use out of this one tool. [08:54.540 --> 08:56.740] So I guess the core idea was to try to do something similar [08:56.740 --> 08:59.320] with initial access payloads. [08:59.320 --> 09:03.060] And, you know, the core idea is to identify discrete payload components [09:03.060 --> 09:07.600] so basically, like, examine, you know, like, your typical payload [09:07.600 --> 09:11.480] and say, what are all the parts that you see in this payload [09:11.480 --> 09:15.720] that kind of repeat themselves across every payload that you ever write? [09:15.760 --> 09:19.280] And, you know, identify those and turn them into modules. [09:20.360 --> 09:22.780] And as a bonus, provide built-in obfuscation encryption [09:22.780 --> 09:24.760] and symbolic substitution capabilities, [09:24.760 --> 09:27.520] which makes it easier to evade signature-based detections. [09:27.520 --> 09:29.160] And in the case of encryption, [09:29.160 --> 09:33.040] makes it easier to, you know, evade human analysts. [09:33.060 --> 09:36.640] And, you know, by doing that, we greatly extend the shelf life [09:36.640 --> 09:39.920] of, you know, those individual payload components that we're writing. [09:42.220 --> 09:44.160] So how would something like this work? [09:45.060 --> 09:46.500] To kind of think about this, right, [09:46.500 --> 09:48.340] we have to talk about how payloads are built. [09:48.760 --> 09:51.200] This is actually, you know, the interesting thing about this project, [09:51.200 --> 09:53.280] this is less of a Red Team project [09:53.280 --> 09:54.700] than it is like a software development project. [09:54.700 --> 09:57.020] Because, like, we're actually not really trying to do [09:57.200 --> 09:59.380] a whole lot of crazy stuff here with the actual... [10:01.800 --> 10:03.020] ...the payload itself. [10:03.020 --> 10:06.340] We're just looking at kind of the abstract design pattern here. [10:07.000 --> 10:09.660] You know, if we think about the anatomy of a payload, [10:09.660 --> 10:12.380] at their core, initial access payloads are relatively simple. [10:12.380 --> 10:14.720] They involve two major steps, which we talked about. [10:14.840 --> 10:16.960] You load the shellcode into memory and you execute it. [10:17.260 --> 10:19.300] A little bit of terminology I'm going to throw out here. [10:19.300 --> 10:21.140] From this point onward in this presentation, [10:21.140 --> 10:23.500] we're going to refer to the routine that performs these two actions [10:23.500 --> 10:26.880] as the executor function, just to kind of make things simple. [10:28.360 --> 10:31.220] So, there are many ways of achieving shellcode execution. [10:31.220 --> 10:32.900] You know, you've got the allele injection, [10:32.900 --> 10:35.620] spawn a local thread, you use process hollowing, [10:35.620 --> 10:37.780] thread execution, hijacking, all kinds of stuff. [10:37.780 --> 10:41.660] But we actually want to abstract away specific details like this. [10:41.660 --> 10:43.600] We don't really want to focus on them quite yet. [10:43.960 --> 10:47.620] Because what we're looking at is actually for more of a bigger picture. [10:49.060 --> 10:50.840] You know, also something else we need to consider, [10:50.840 --> 10:51.830] we mentioned that we need to... [10:54.400 --> 10:56.380] ...contend with application whitelisting. [10:56.380 --> 10:58.580] And that really means that we're limited to formats [10:58.580 --> 11:03.900] that can be executed by LullBoss, you know, [11:03.900 --> 11:05.440] LullBoss for land buyers and scripts. [11:06.040 --> 11:08.160] So, what this means is that our initial access payload [11:08.160 --> 11:10.740] is really going to require three basic components. [11:10.740 --> 11:13.020] And you can kind of see my diagram here on the left here. [11:13.120 --> 11:14.740] We're going to have the shellcode runner. [11:14.740 --> 11:17.320] Technically, the whole entire thing is a shellcode runner. [11:17.320 --> 11:20.820] But we'll, just for the sake of labeling things, [11:20.820 --> 11:23.840] you know, we'll refer to this outer wrapper as a shellcode runner. [11:23.840 --> 11:26.220] That's going to be LullBoss specific, right? [11:26.680 --> 11:28.500] You know, if it's MSBuild payload, [11:28.500 --> 11:30.340] that's going to be like an XML file, basically. [11:30.340 --> 11:32.300] If it's an installutil payload, [11:32.300 --> 11:35.540] that's going to be a C sharp file that's compiled into an assembly. [11:35.840 --> 11:37.820] But you have your outer shellcode runner. [11:38.080 --> 11:39.860] And then you have your payload name. [11:39.880 --> 11:41.260] That's your application entry point. [11:41.260 --> 11:42.940] That's going to call your executor function [11:42.940 --> 11:45.180] and really everything else that gets called within your payload. [11:45.180 --> 11:47.000] But we're not going to worry about everything else yet. [11:47.480 --> 11:49.020] It's just these three components. [11:49.620 --> 11:51.860] And then finally, you have your executor function. [11:51.860 --> 11:53.760] And this is going to load your software to memory, [11:53.760 --> 11:57.140] execute it, and, you know, essentially, [11:57.140 --> 11:59.940] yeah, that's the meat of this payload so far. [12:00.820 --> 12:04.040] So DropEngine implements these basic components as base classes. [12:04.560 --> 12:08.200] Essentially, what I've done is I've taken these three components [12:08.200 --> 12:12.280] and made it so you can inherit from them and derive modules from them. [12:12.280 --> 12:15.020] And what this means is that you can just write a module, [12:15.020 --> 12:16.800] and you can use any executor type you want, [12:16.800 --> 12:18.680] wrap it in any shellcode runner you want. [12:18.680 --> 12:20.880] And the overall structure of the payload remains the same, [12:20.880 --> 12:22.120] despite that you have a lot of different options [12:22.120 --> 12:24.720] as to how to actually implement all this stuff. [12:26.120 --> 12:27.800] To kind of give you an example, you know, [12:27.800 --> 12:29.060] we're talking about the structure. [12:29.340 --> 12:31.720] You know, this is a... I ripped this direct... [12:32.720 --> 12:34.440] Well, there's supposed to be a link to this GitHub, [12:34.440 --> 12:36.580] but I guess, like, it's getting cropped on the bottom [12:36.580 --> 12:39.860] because it's PowerPoint and Zoom. [12:39.860 --> 12:44.480] But yeah, this is from 0x13steveflores' GitHub. [12:44.480 --> 12:46.000] It's from a project called MoveKit. [12:46.000 --> 12:49.300] This is just an MSBuild runner, right? [12:49.300 --> 12:53.240] You have your outer wrapper, [12:53.240 --> 12:55.240] which is what we talked about here, right? [12:55.240 --> 12:56.780] And this is just your XML file. [12:56.780 --> 12:59.440] You have your payload main, which is just importing stuff [12:59.440 --> 13:01.240] and calling this executor here. [13:01.240 --> 13:05.320] And then you have your actual executor function there, [13:05.320 --> 13:06.260] your shellcode inject. [13:09.040 --> 13:10.580] So... and this is going to be interesting. [13:10.580 --> 13:12.300] I have to switch back and forth here a little bit. [13:12.300 --> 13:13.640] I'm actually going to stop sharing for a second [13:14.440 --> 13:18.220] and then reshare from Hyper. [13:19.300 --> 13:19.820] Cool. [13:19.940 --> 13:23.540] So, yeah, you're going to see a lot of other stuff here, [13:23.540 --> 13:27.160] but if you look at the overall structure of how things are done, [13:27.160 --> 13:37.120] we have our payload main components, [13:37.540 --> 13:39.940] have our runners. [13:39.940 --> 13:43.180] We can break them into individual discrete components like that. [13:43.300 --> 13:46.260] And we'll kind of go into more depth in this in a little bit. [13:46.400 --> 13:49.040] And then, of course, we have our executor functions, [13:49.040 --> 13:50.920] which I don't have a whole lot of them in there quite yet, [13:50.920 --> 13:52.500] but that's okay. [13:53.220 --> 13:58.360] So I'm going to stop this in an attempt to share this again. [13:58.360 --> 13:59.940] Okay, there we go. [14:00.360 --> 14:03.040] And then hit from current slide. [14:03.040 --> 14:03.840] Okay. [14:04.360 --> 14:09.280] So we've identified our discrete components here, right? [14:09.280 --> 14:11.380] These items here. [14:13.080 --> 14:18.080] We also want to throw in encryption capabilities. [14:18.080 --> 14:23.040] It's typically a good idea to leverage encryption when creating initial access payloads [14:24.440 --> 14:26.280] for multiple reasons. [14:26.460 --> 14:30.300] Basically, you have your shellcode that is going to be executed by your shellcode runner. [14:33.020 --> 14:36.380] A lot of these are going to be like binary payloads or something like that. [14:36.580 --> 14:39.000] You don't necessarily want to have to throw that whole entire thing out [14:39.000 --> 14:43.400] just because that particular signature is detected by antivirus. [14:43.400 --> 14:50.320] What we do is, one way of hiding that from signature-based checks is by encrypting it. [14:50.560 --> 14:55.000] But the other advantage of encrypting your shellcode is that it makes it more difficult [14:55.000 --> 14:57.380] for human analysts to reverse engineer our payload. [14:57.640 --> 15:00.500] Remember, we need to assume that the payload is eventually going to get caught. [15:01.000 --> 15:05.680] And when it does, we want to make it as difficult for the reverse engineer [15:05.680 --> 15:07.720] to pick this apart as humanly possible. [15:09.600 --> 15:16.060] What this means is that our updated payload execution process [15:16.600 --> 15:19.100] is actually going to involve a few more steps. [15:19.100 --> 15:23.090] We are going to load the encrypted payload into memory. [15:23.600 --> 15:29.420] We're going to decrypt that payload using an encryption key to obtain plaintext shellcode. [15:29.780 --> 15:33.680] And then finally, we're going to load that plaintext shellcode into memory and execute it. [15:33.880 --> 15:37.700] So the extra step here that we've added is this encryption function. [15:40.500 --> 15:45.820] If we're going to use encryption, this introduces yet another thing that we have to account for, [15:45.820 --> 15:48.160] and that's key storage, derivation, and retrieval. [15:48.660 --> 15:51.960] When we leverage encryption to protect our shellcode, [15:51.960 --> 15:55.800] essentially this is going to require us to provide our payload with one of the following. [15:55.920 --> 15:58.700] It's either going to need to be able to derive the encryption key somehow [15:58.700 --> 16:00.700] without actually storing it. [16:00.700 --> 16:03.880] So it's not going to store it, but we need to be able to obtain the encryption key somehow. [16:03.880 --> 16:07.220] It needs to go... if we can't do that, [16:07.220 --> 16:11.860] it could possibly just retrieve the encryption key from some other location. [16:11.860 --> 16:13.620] So we could provide it with that capability. [16:14.060 --> 16:17.880] Or we could just store the encryption key itself in the payload. [16:17.880 --> 16:22.680] Now, obviously, this last option is not ideal because, you know, [16:22.680 --> 16:24.940] if you're storing the encryption key in the shellcode, [16:24.940 --> 16:27.000] if someone compromised in the payload, [16:27.000 --> 16:28.960] then someone compromises the payload, [16:28.960 --> 16:31.080] then they can decrypt the shellcode and you're kind of... [16:31.640 --> 16:33.220] you're just adding an extra step, [16:33.220 --> 16:38.600] but you're not really making it terribly difficult to pick apart. [16:40.320 --> 16:42.820] So let's talk about this first option a bit. [16:42.980 --> 16:47.440] We mentioned the use of... [16:48.360 --> 16:51.060] the first option is to derive the encryption key. [16:51.900 --> 16:56.400] One really great way of doing this is the use of environmental keying. [16:56.420 --> 16:57.800] This is like a really... [16:58.260 --> 17:02.000] I mean, so environmental keying has been around for a pretty long time. [17:02.000 --> 17:04.600] I mean, there's a lot, if you just look up like Mauer, [17:04.600 --> 17:07.020] you know, environmental keying and just Google it, [17:07.640 --> 17:10.200] there's just tons of papers written about the subject. [17:10.320 --> 17:16.160] I think that the three most relevant projects to check out though, [17:16.160 --> 17:17.080] in terms of like prior work, [17:17.080 --> 17:19.220] that's like really relevant to red teaming, [17:19.220 --> 17:20.220] would definitely be... [17:22.080 --> 17:23.780] well, Ebola is the classic one, you know, [17:24.260 --> 17:27.700] that, yeah, that's... [17:28.480 --> 17:30.760] so if you look up Ebola GitHub, [17:30.760 --> 17:34.060] like that one is going to come up really, [17:34.060 --> 17:36.000] and environmental keying, that one will come up. [17:36.000 --> 17:38.280] The other one is Spotter, [17:38.280 --> 17:40.140] that one was released fairly recently, [17:40.140 --> 17:42.240] I think like in 2018 or something like that. [17:42.280 --> 17:45.100] And, you know, it pretty much, you know, does something pretty similar. [17:46.400 --> 17:47.460] And then also there's... [17:48.560 --> 17:53.160] I think like Leo Lupik has some blog posts where he talks about this [17:53.160 --> 17:55.880] and also expands off of those. [17:56.440 --> 17:58.960] But yeah, so the idea with environmental keying [17:58.960 --> 18:01.140] is that you actually derive the encryption key [18:01.140 --> 18:04.920] either entirely or in part from values in the environment. [18:05.000 --> 18:06.520] So what do we mean by this? [18:06.520 --> 18:09.660] Well, I mean, let's say that, you know, [18:09.660 --> 18:11.100] by attributes in the environment, [18:11.100 --> 18:12.680] you know, we're talking about usernames. [18:13.040 --> 18:17.700] So for example, you could use the currently logged in user [18:17.700 --> 18:20.200] that your payload is running as, [18:21.420 --> 18:22.860] as part of the encryption key. [18:22.860 --> 18:25.440] You could, you know, try to obtain the external IP address [18:25.440 --> 18:29.700] from where your payload is executing [18:29.700 --> 18:33.280] and use that as part of the encryption key. [18:33.280 --> 18:34.700] You could, you know, use your... [18:34.700 --> 18:36.460] make sure that you're actually on the right computer [18:36.460 --> 18:40.480] by deriving the encryption key in part [18:40.480 --> 18:43.080] by using your internal FQDN. [18:43.660 --> 18:44.840] I actually didn't like... [18:44.840 --> 18:47.060] you could even like use the moon phase or something like that. [18:47.060 --> 18:48.220] I mean, you can, you know, [18:48.220 --> 18:50.020] but essentially what this lets you do... [18:50.560 --> 18:52.440] well, there's two things. [18:53.580 --> 18:58.680] One, it makes your payload very, very resistant to analysis [18:58.680 --> 19:00.160] because your encryption key is now [19:00.160 --> 19:02.060] no longer being stored in the payload. [19:02.240 --> 19:03.420] And essentially they'd have to, you know, [19:03.420 --> 19:05.480] essentially like if you're setting encryption key [19:05.480 --> 19:08.400] to the value of the hard drive serial number, [19:08.400 --> 19:10.520] you know, that means that you'll be able to decrypt [19:10.520 --> 19:12.900] and execute your payload on a specific machine [19:12.900 --> 19:15.800] that has that particular hard drive plugged in. [19:16.680 --> 19:18.260] But if you're an analyst [19:18.260 --> 19:21.300] and you just have a copy of this payload, [19:21.300 --> 19:28.000] unless you know what specific machine you're going after [19:28.000 --> 19:29.280] and what the serial number is, [19:29.280 --> 19:32.960] you're essentially forced to attempt to crack that encryption [19:32.960 --> 19:35.700] by guessing the value of that serial number. [19:35.700 --> 19:39.060] So it makes your payload super hard to crack. [19:39.060 --> 19:41.560] And the added advantage is that it's very targeted. [19:43.280 --> 19:44.960] Your shellcode is only going to be decrypted [19:44.960 --> 19:47.520] on machines that match the key's specific attributes [19:47.520 --> 19:48.960] or if someone says they're brute forcing [19:48.960 --> 19:50.680] for a very, very long time. [19:53.980 --> 19:56.940] So I'm now going to set the first live demo of this. [19:57.460 --> 19:59.140] Over Zoom, no less. [19:59.280 --> 20:00.620] All right. [20:00.620 --> 20:03.380] So I'm going to do a couple of things. [20:03.380 --> 20:05.480] First, I'm going to show you my setup that I'm using for this, [20:05.480 --> 20:06.720] because I think that's important, [20:06.720 --> 20:09.940] just so you all know kind of what's going on here. [20:09.940 --> 20:11.520] So I'm going to stop sharing for one second [20:11.520 --> 20:14.020] and I'm literally going to share. [20:15.200 --> 20:16.380] Well, can I do that? [20:18.000 --> 20:19.180] Okay, actually, yeah. [20:19.180 --> 20:20.800] So the first thing I have to show you, [20:23.370 --> 20:25.270] security settings on this machine that I'm using, [20:25.270 --> 20:27.570] because that's actually very relevant. [20:33.760 --> 20:36.240] And you should see it. [20:36.260 --> 20:39.520] Okay, let me try sharing this again. [20:45.500 --> 20:46.720] Oh, you know what I can do? [20:46.980 --> 20:47.860] Yeah, here it is. [20:47.860 --> 20:49.280] Okay, I got it. [20:49.280 --> 20:52.340] So as you can see, I don't have cloud delivery protection [20:52.340 --> 20:54.680] because I don't want the stuff I'm working on at the moment [20:54.680 --> 20:58.680] to get shipped off to antivirus analysis land, essentially. [20:58.680 --> 21:02.560] So that's turned off, as well as automatic sample submission. [21:02.560 --> 21:06.020] But this is a brand new Windows 10 install. [21:06.620 --> 21:09.200] I have real-time protection turned on. [21:09.880 --> 21:13.240] Tamper protection is turned on, so you can't disable it. [21:13.940 --> 21:15.920] But I do have an exclusion setup, [21:15.920 --> 21:17.760] and I want to explain this really fast [21:17.760 --> 21:21.400] in case you're wondering why certain things aren't working. [21:21.580 --> 21:24.000] So I have one exclusion here, [21:24.000 --> 21:26.400] and this is this directory, demo AB include. [21:26.400 --> 21:28.240] So essentially, what I'm going to be doing during these demos [21:28.780 --> 21:31.980] is I have four, and I'm going to have to now [21:35.860 --> 21:38.000] switch windows that I'm sharing again. [21:38.040 --> 21:40.020] So you should see hyper right now. [21:40.020 --> 21:40.920] There's four terminals. [21:40.920 --> 21:43.400] I'm going to try to make this a little cleaner. [21:46.910 --> 21:50.050] So in the top left, this is just for my benefit. [21:50.050 --> 21:52.710] That's essentially, I'm trying not to anger the demo gods. [21:53.130 --> 21:57.410] So I am keeping as much of this stuff in the text file, [21:57.410 --> 21:58.610] and I'm going to run the commands that are in there [21:58.610 --> 22:00.230] rather than trying to just guess. [22:00.730 --> 22:02.150] This will be relevant later. [22:02.150 --> 22:03.950] This is going to be a remote key server, [22:03.950 --> 22:06.590] and you can kind of... we'll talk about that in a second. [22:06.590 --> 22:07.830] This is a Metasploit instance. [22:07.830 --> 22:09.770] So this is... yeah, so we're actually going to use [22:09.770 --> 22:10.630] Meterpreter for this. [22:10.630 --> 22:14.670] So every AV engine under the sun should be able to detect [22:14.670 --> 22:16.810] what we're doing, essentially, is what I'm trying to say. [22:16.810 --> 22:18.870] We're just using... the payload we're going to be using [22:18.870 --> 22:21.630] is going to be just a plain Meterpreter [22:21.630 --> 22:23.670] reverse HTTPS. [22:23.970 --> 22:27.030] We have to use HTTPS because the actual unencrypted traffic [22:27.030 --> 22:29.350] will be picked up immediately. [22:30.810 --> 22:32.760] So that exclusion that we're seeing... [22:35.030 --> 22:36.610] I'm just being difficult. [22:36.610 --> 22:37.140] I'm going to have to... [22:38.610 --> 22:43.050] It's going to be in this directory here. [22:43.750 --> 22:45.150] I'm going to AV exclude. [22:45.150 --> 22:47.570] And this is because we're going to be building this payload, [22:47.570 --> 22:49.970] and although the payload was generated here, [22:49.970 --> 22:54.830] the second I SCP that payload over onto my main machine, [22:54.830 --> 22:59.310] which is what you're seeing in this top right terminal here, [22:59.310 --> 23:00.930] Defender would just nuke that. [23:00.930 --> 23:03.630] And I really don't want to just keep turning Defender on and off [23:03.630 --> 23:05.050] every time I have to do a demo, [23:05.050 --> 23:07.210] which is because that's just going to... [23:07.210 --> 23:09.390] I'm trying to make this go as smoothly as possible. [23:10.870 --> 23:14.230] So the compromise here is that we're going to be pulling [23:14.230 --> 23:16.990] our actual shellcode out of demo AV exclude. [23:16.990 --> 23:19.130] But when we execute it, that's not where we're executing from. [23:19.130 --> 23:21.470] We're going to be executing outside of that exclusion folder. [23:22.310 --> 23:28.110] Okay, with that out of the way, let's show you how to go over... [23:38.800 --> 23:45.180] Let's go over how we'd make a payload using environmental keying. [23:45.400 --> 23:47.380] So essentially, the first thing we're going to do [23:48.940 --> 23:52.540] is get a list of available models, right? [23:52.540 --> 23:53.640] And just run this. [23:53.640 --> 23:57.420] And these are all the different payload components we can choose from. [23:57.420 --> 23:59.940] So let's say that we want to use environmental keying. [23:59.940 --> 24:01.340] We want to essentially grab... [24:04.420 --> 24:07.700] Let's do the FQDN, because I have that written down, [24:08.840 --> 24:10.380] and my current username. [24:10.380 --> 24:12.460] So we're going to derive the key from that. [24:12.700 --> 24:14.840] In that case, we could just do this. [24:14.840 --> 24:21.480] We could do Python, prop engine, [24:21.480 --> 24:23.740] break onto a new line here, [24:23.740 --> 24:25.740] specify that our shellcode should be... [24:27.620 --> 24:33.980] You know, in that demo, maybe exclude to shell. [24:35.180 --> 24:37.760] We're going to use an interface... [24:37.760 --> 24:39.960] So the interface, I'm specifying this command interface. [24:39.960 --> 24:42.080] That's like literally the glue that holds everything together. [24:42.080 --> 24:44.920] You know, if you're working in C-sharp, you're going to use a C-sharp interface. [24:45.140 --> 24:46.900] Don't worry about that too much. [24:47.120 --> 24:51.980] But we're going to say, C-sharp runner interface, right? [24:52.500 --> 24:54.480] And then we're going to also look at... [24:54.480 --> 24:55.840] Just like this encryption key. [24:55.840 --> 24:58.280] We need an encryption key and a decryption key. [24:58.880 --> 25:06.140] So the EQ keys we're going to use are going to be this external FQDN that we talked about. [25:06.760 --> 25:08.400] And notice I'm using more than one. [25:08.440 --> 25:12.340] We'll kind of go into how that works in a second, right? [25:14.890 --> 25:16.370] I'm just going to use the decryption keys, [25:16.370 --> 25:18.850] which is essentially these things, but written in C-sharp. [25:22.080 --> 25:24.900] I'm just going to copy these, put them in there. [25:26.540 --> 25:28.120] We're then going to need to select a encryptor. [25:28.120 --> 25:29.540] It's doing encryptor shellcode. [25:30.240 --> 25:33.300] So we're going to say, encryptor AES. [25:33.300 --> 25:35.360] We're just going to use AES-256. [25:36.180 --> 25:38.780] That should really be named AES-256, not just AES. [25:38.780 --> 25:39.960] I should change that. [25:40.280 --> 25:41.820] And we're going to use a decryptor. [25:42.520 --> 25:46.160] So decryptor C-sharp, origin doll AES, [25:46.160 --> 25:51.020] which is the corresponding decryption function that we need. [25:52.000 --> 25:55.640] Finally, for our shellcode, we'll go ahead and use msbuild, [25:55.640 --> 25:57.700] because that will save you from having to compile something, [25:57.700 --> 25:59.320] which will take extra time. [26:02.940 --> 26:04.520] And then we're going to need a mutator. [26:04.520 --> 26:07.560] We haven't really talked about mutators yet, but we will. [26:09.380 --> 26:13.000] But for now, I'm going to say mutator string. [26:13.220 --> 26:14.320] And essentially, what that's going to do, [26:14.320 --> 26:17.300] it's going to take all the variable names in our finished output [26:17.300 --> 26:18.840] and change them to a random string. [26:18.840 --> 26:21.720] So it just makes it a little harder to signature around. [26:22.320 --> 26:23.560] And that really is... [26:23.560 --> 26:27.780] Oh, we also need to specify the actual username and external FQDN [26:27.780 --> 26:30.120] that we're trying to use for our key. [26:30.120 --> 26:36.240] So I'll put my username as FQDN. [26:36.400 --> 26:38.460] And I'm just going to copy it from here. [26:38.460 --> 26:41.520] And hopefully, this is an update in the last time, like in the past hour or so. [26:41.520 --> 26:42.800] I don't think it would have. [26:43.360 --> 26:46.560] And finally, oops, I forgot something. [26:48.840 --> 26:50.340] We need an executor function. [26:50.340 --> 26:53.440] Yeah, so we need that executor function that actually executes our shellcode. [26:53.440 --> 26:56.780] And we're just going to use C-sharp virtual alloc thread. [26:57.700 --> 27:01.420] And so you may call it virtual alloc, virtual protect, and all that. [27:02.940 --> 27:06.600] And we're going to make our output file example.csproj. [27:06.600 --> 27:09.200] And that's going to be our MSBuild file. [27:09.280 --> 27:09.620] Cool. [27:09.620 --> 27:10.340] Looks like it ran. [27:10.340 --> 27:11.240] Didn't get any errors. [27:11.240 --> 27:17.360] If you look at our example.csproj, here is an obfuscated MSBuild file. [27:18.280 --> 27:23.140] Actually, I should probably show you what this is actually doing. [27:24.640 --> 27:27.760] I'm going to do mutate or null, which basically means don't mutate anything. [27:30.260 --> 27:35.160] But yeah, so basically, here are all the different components that are stacked together. [27:35.160 --> 27:40.320] Here are your decryption keys, and your decryptor, and your executor, and everything else. [27:40.360 --> 27:43.540] And then here's your actual payload itself and payload name. [27:43.540 --> 27:47.340] Essentially, all this is just being rendered into the payload by DropEngine. [27:47.840 --> 27:48.640] Automagically. [27:49.440 --> 27:51.080] And finally, I run everything down there. [27:51.740 --> 27:54.080] But I want this to be random, because I don't know. [27:54.080 --> 27:55.200] Demo gots, I guess. [27:55.620 --> 27:57.360] So I made that a random one. [27:58.120 --> 27:59.820] So now we're going to set up our handler. [28:00.580 --> 28:04.380] Use exploit multihandler payload for CTP. [28:06.160 --> 28:11.220] Lhost set Lport 443, which should be correct. [28:11.220 --> 28:15.180] And I'm going to set exploit-j to start our handler in the background. [28:15.800 --> 28:19.220] And then we're going to actually run this using AliceBuild. [28:19.580 --> 28:21.660] And there we go. [28:21.960 --> 28:28.260] Now, just to kind of, in case you don't believe me, that this is actually doing something. [28:30.900 --> 28:33.180] I'm going to kill everything here. [28:38.990 --> 28:41.050] That was a bad sign. [28:41.050 --> 28:50.930] But I copy of the enter nano. [28:52.050 --> 28:52.610] All right. [28:52.610 --> 28:53.050] You know what? [28:53.050 --> 28:55.430] I'm actually deviating from the demo right now. [28:55.430 --> 28:57.570] And I think that's a bad idea. [28:57.570 --> 28:59.630] We'll get back to this if we have time. [29:01.950 --> 29:03.030] No, actually, you know what? [29:03.030 --> 29:03.890] I'm stubborn. [29:03.890 --> 29:04.690] Let's do the... [29:08.740 --> 29:14.980] Yeah, I copy demo AV exclude empty shell. [29:14.980 --> 29:17.560] And let's just copy it up on level. [29:18.720 --> 29:24.090] We should get alert. [29:25.950 --> 29:27.110] Or perhaps not. [29:27.110 --> 29:29.370] Maybe we might have to run it to get the alert. [29:30.270 --> 29:32.750] But yeah, I'm not going to say you're tinkering with this. [29:36.050 --> 29:37.610] Let's get back to PowerPoint. [29:38.930 --> 29:39.810] OK. [29:39.910 --> 29:40.970] From current slide. [29:42.650 --> 29:44.710] So that's our payload. [29:44.710 --> 29:51.310] Basically, custom build payload with environmental keying that we literally just created in a second. [29:54.230 --> 29:56.490] So mutator modules, right? [29:58.210 --> 30:00.070] We mentioned also that we're using... [30:10.280 --> 30:11.000] Ignore me. [30:11.000 --> 30:13.100] I could have sworn there was something else that I was supposed to talk about there. [30:13.100 --> 30:13.620] OK. [30:13.820 --> 30:14.200] Yeah. [30:14.200 --> 30:16.420] So the other thing, essentially what we've just done. [30:17.020 --> 30:21.580] We've said, here's the executor function we want to use. [30:21.700 --> 30:24.000] Here's the shellcode runner we want to use. [30:24.000 --> 30:26.700] Here's the encryption decryption routines we want to use. [30:26.900 --> 30:30.000] And by the way, we want to derive our keys from these two specific functions. [30:30.000 --> 30:32.280] And we're going to pull this stuff together and make it into a payload. [30:32.280 --> 30:37.500] And by the way, randomize all the variables in variable names in that payload. [30:37.800 --> 30:40.460] And just write a command, and then it just does it. [30:40.460 --> 30:42.520] And then voila, you have a payload. [30:43.080 --> 30:44.620] The way that we did the actual... [30:44.620 --> 30:50.940] The changing of the variable names was using basically modular symbolic mutation. [30:50.940 --> 30:54.420] So DropEngine supports the use of mutator modules that... [30:54.420 --> 30:55.640] I mean, essentially what they do is that they... [30:56.700 --> 31:03.200] Every module that corresponds to something that has variable names or function names [31:03.200 --> 31:09.100] has a mutator method that gets called in the back end by whatever mutator module that you select. [31:09.100 --> 31:11.460] And the mutator module then systematically goes through [31:11.460 --> 31:18.700] and takes a list of variable names and maps them using some algorithm. [31:18.700 --> 31:21.720] The algorithm is irrelevant. It's module specific. [31:22.460 --> 31:23.980] And then when the actual... [31:23.980 --> 31:29.380] And returns back to that module, the original module, that mapping. [31:29.380 --> 31:31.680] So like a dictionary of like, here's all your variable names, [31:31.680 --> 31:33.320] and here's the stuff that we've mapped them to. [31:33.320 --> 31:35.300] And then what happens is that when you render... [31:35.300 --> 31:38.980] When that module gets rendered into a rendered template, [31:38.980 --> 31:40.300] and that's how we're building everything. [31:40.300 --> 31:41.720] It's using Jinja templates. [31:43.680 --> 31:44.640] We are... [31:44.640 --> 31:48.280] Essentially what's going on is that it looks at that mapping [31:48.280 --> 31:51.480] in order to figure out what's in the variable. [31:51.480 --> 31:55.080] So this is pretty cool because it allows us to create payloads that, [31:55.080 --> 31:58.140] you know, circumvent signature-based detections pretty easily. [31:58.300 --> 32:02.160] I only have like three supported methods in there right now. [32:02.300 --> 32:05.840] Rot13, the random string, and also symbol substitution using a word list. [32:05.840 --> 32:08.180] Null mutator doesn't really count because that's just... [32:08.180 --> 32:09.220] It just doesn't do anything. [32:09.220 --> 32:10.280] It's a null mutator. [32:10.280 --> 32:12.660] It's primarily there for debugging purposes. [32:13.840 --> 32:15.680] And I've kind of already demonstrated that, [32:15.680 --> 32:17.690] but if you want to just go over... [32:18.680 --> 32:21.980] Just once again, what that looks like. [32:22.180 --> 32:28.260] You know, take this one that we just did, [32:28.260 --> 32:30.340] just print to the screen instead of out the file. [32:30.520 --> 32:32.010] So for example, here's your... [32:33.200 --> 32:34.320] Actually, let me use... [32:34.320 --> 32:38.720] I've got another piece of shellcode that isn't so long that we can use for demos. [32:41.080 --> 32:45.360] Yeah, so, you know, here's your random strings. [32:45.740 --> 32:46.960] You know, if you wanted to use... [32:49.880 --> 32:50.760] Rot13. [32:53.200 --> 32:57.200] These look an awful lot like the variable names. [32:57.540 --> 32:59.080] Let's use a word list. [33:02.050 --> 33:04.730] You actually have to specify a word list when you do this. [33:04.730 --> 33:06.230] Let's use US cities. [33:06.230 --> 33:07.130] And that will... [33:07.130 --> 33:09.170] Now all your variable names are corresponding to US cities. [33:09.170 --> 33:11.790] A better use of this would just be to make a word list [33:11.790 --> 33:13.710] that actually are believable variable names. [33:13.710 --> 33:18.470] But I don't know, this is better for doing a demo. [33:19.090 --> 33:20.490] Let me go back to PowerPoint. [33:20.870 --> 33:22.370] Let's move on from here. [33:28.370 --> 33:30.010] And let me just make sure... [33:30.010 --> 33:30.950] Okay, cool. [33:32.810 --> 33:36.270] So let's talk about some more keying techniques that we support. [33:36.830 --> 33:38.490] We talked about environmental keying. [33:38.490 --> 33:39.730] Remote keying is also pretty neat. [33:39.730 --> 33:43.690] Essentially, instead of deriving the key from some place in your environment, [33:43.690 --> 33:47.650] you're actually going to retrieve the encryption key from some remote location, [33:47.650 --> 33:52.570] you know, either for HTTP or HTTPS, DNS, or some other communication protocol. [33:53.410 --> 33:54.750] This is actually... [33:54.750 --> 33:57.230] You know, if you have well-designed non-attributable attack infrastructure, [33:57.230 --> 33:59.810] it actually makes this method pretty effective. [33:59.810 --> 34:01.950] You know, you can place the key server behind a redirector [34:02.770 --> 34:05.570] and only accept requests for that key on very specific... [34:06.270 --> 34:09.710] for very specific profile traffic that's being sent to the redirector. [34:09.730 --> 34:13.710] If you want to make it even better, you can use a one-time remote key, [34:13.710 --> 34:16.330] which is a variant in which your key server, [34:16.330 --> 34:18.130] which is the server that's hosting these remote keys... [34:19.230 --> 34:21.570] By the way, you want to have one key per payload, [34:21.570 --> 34:23.270] and DropEngine does support that. [34:25.030 --> 34:27.690] So keys should be unique to the payload that you generate. [34:28.270 --> 34:31.310] But essentially, the one-time remote key variant, [34:31.310 --> 34:36.510] once that key is successfully retrieved from the key server, [34:37.050 --> 34:39.910] it actually is deleted from the key server. [34:39.910 --> 34:43.570] So the key server goes back into its database and just nukes the key. [34:43.590 --> 34:45.870] And what this means is that any future requests for that key [34:45.870 --> 34:47.990] are either going to be ignored by the key server, [34:47.990 --> 34:49.890] or return some kind of junk data, [34:49.890 --> 34:53.810] or you could even, at that point, respond to that kind of request [34:53.810 --> 34:54.890] by returning a redirect. [34:54.890 --> 34:56.570] So you could do what a redirect would do [34:56.570 --> 34:59.890] and redirect that request to something innocuous, [34:59.890 --> 35:01.970] like, you know, remotely hosted jQuery or something. [35:01.970 --> 35:04.810] Like, look, it's not... it's just jQuery, right? [35:04.810 --> 35:08.030] But so, I mean, there are obviously some obvious advantages [35:08.030 --> 35:09.250] to doing keying this way. [35:09.290 --> 35:11.230] It's very resistant to analysis. [35:11.430 --> 35:13.790] The encryption key is not stored on the payload file. [35:14.090 --> 35:18.230] And it's hopefully being protected in transit using TLS. [35:18.710 --> 35:22.270] It's also less targeted, right? [35:22.270 --> 35:26.050] You know, while highly targeted payloads are good in a lot of cases, [35:26.050 --> 35:26.810] sometimes they're not. [35:26.810 --> 35:29.410] Sometimes you don't just want to attack the computer [35:29.410 --> 35:32.350] of that one person that has that particular hard drive or username. [35:32.350 --> 35:34.590] Sometimes you want a little more breadth. [35:34.590 --> 35:37.890] In this case, you don't have to limit your scope. [35:38.810 --> 35:40.710] I mean, you should limit your scope regardless. [35:40.710 --> 35:44.390] But I guess what I'm saying is the scope isn't, you know, [35:44.390 --> 35:48.330] implicitly limited by your keying mechanism at this point. [35:51.530 --> 35:55.810] So I'll show you how this works in Dropbox really fast. [35:57.310 --> 36:00.330] And I'm going to go back to my screen here, go back to Hyper. [36:04.400 --> 36:08.420] And so in the bottom left, we have this, what looks like a Flask app. [36:08.860 --> 36:10.480] It's really, really basic. [36:11.700 --> 36:13.800] I honestly didn't put a whole lot of time into this because, you know, [36:13.800 --> 36:15.780] I was just trying to get the proof of concept out the door. [36:15.780 --> 36:19.440] But this is our remote one-time key server. [36:19.460 --> 36:25.060] And what we're going to do here is do a very similar payload [36:27.140 --> 36:29.440] to what we just did, right? [36:33.920 --> 36:34.800] Hang on, let me... [36:48.190 --> 36:49.670] So we're going to grab this. [36:51.590 --> 36:57.050] And this is, you know, as you can see here, well, it's just RAM. [36:57.050 --> 37:01.590] But what we just did, we created a shellcode using our empty shell, [37:01.590 --> 37:06.030] like our interpreter shell that's in that empty shell.bin file. [37:06.550 --> 37:08.730] It's pretty much the same attributes we used last time. [37:08.730 --> 37:11.830] The difference here is we actually added some keying components. [37:12.290 --> 37:16.550] We added a new key here, which you can see right here. [37:16.550 --> 37:20.530] It's the D-key one-time remote HTTP and the corresponding decryption key, [37:20.530 --> 37:24.090] which is their D-key remote C-sharp OTK HTTP. [37:24.490 --> 37:27.270] And essentially what this is doing is it's just providing functions [37:27.270 --> 37:30.470] that will attempt to reach out to this server right here [37:30.470 --> 37:33.250] that is running at the bottom left to retrieve this encryption key. [37:33.250 --> 37:35.410] And it's going to use that by using a specific identifier [37:35.410 --> 37:37.690] that you need to your implant. [37:38.090 --> 37:40.930] So that, you know, essentially what this guy down here is going to do [37:40.930 --> 37:43.590] is look in the database to see if that identifier exists. [37:43.590 --> 37:47.890] And if it does, it's going to respond with the decryption key [37:47.890 --> 37:50.270] and send it back to our payload. [37:50.270 --> 37:53.450] And then, you know, it'll be deleted from the database. [37:53.450 --> 37:56.070] So subsequent requests just won't be honored. [37:57.710 --> 37:59.990] So let's run that really fast. [38:00.430 --> 38:03.310] We just kind of prep the bottom left here. [38:03.610 --> 38:07.030] Make sure we don't have any stragglers either in our sessions or... [38:08.430 --> 38:09.750] Oh, okay, cool. [38:09.750 --> 38:11.610] So we're going to run our handler. [38:14.270 --> 38:16.170] And we're going to rebuild this really fast [38:16.170 --> 38:18.710] just to make sure everything looks selfless enough. [38:18.710 --> 38:19.650] It does. [38:21.670 --> 38:24.210] And we're going to call it MSBuild once again. [38:25.630 --> 38:27.270] And there we go. [38:27.810 --> 38:30.970] And you'll notice here, this traffic showed up in the Flask app. [38:30.970 --> 38:35.930] And that is our server going back. [38:35.930 --> 38:38.170] That's our payload retrieving the key, right? [38:38.170 --> 38:54.230] Now, let's go ahead and kill this session right here, right? [38:56.670 --> 38:59.130] And the reason why I'm doing that is I want to show you what happens when we... [39:00.150 --> 39:03.450] So we've already retrieved that remote key. [39:03.450 --> 39:05.810] So what we're going to do now is we're going to just kind of demonstrate. [39:06.590 --> 39:09.870] If we happen to curl for that same value, right? [39:10.290 --> 39:14.550] Let's say we do a curl request to 127. [39:14.550 --> 39:18.030] This is running on mobile, so we can just do this. [39:22.570 --> 39:25.130] HTTP//, we're not using SSL at the moment. [39:30.150 --> 39:30.910] Oh, you know what? [39:30.910 --> 39:33.130] We'd actually need the implant ID, wouldn't we? [39:33.470 --> 39:34.490] Oh, no, here it is. [39:34.490 --> 39:36.970] Yeah, let's grab this implant ID right from here. [39:37.390 --> 39:37.890] Cool. [39:37.890 --> 39:39.990] So we have everything we need to make this work. [39:41.250 --> 39:48.530] And you'll see that we don't actually get a response at this time because it's been cleared. [39:49.830 --> 39:53.530] All right, so back to our PowerPoint. [39:54.610 --> 39:56.590] We've got about 20 minutes left. [39:56.590 --> 39:58.910] Open this up for chat for about 10. [40:00.090 --> 40:02.330] Let's go back here. [40:04.590 --> 40:06.130] Press slide. [40:06.130 --> 40:06.570] All right. [40:10.500 --> 40:19.880] So one thing you'll notice is that we're actually using multiple encryption keys here. [40:19.880 --> 40:20.880] Or it seems like it, right? [40:20.880 --> 40:25.020] Because we're specifying these different key types and combining them to create a final [40:25.020 --> 40:26.040] encryption key. [40:26.200 --> 40:30.140] We're doing this using something that I like to call key stacking. [40:32.280 --> 40:33.860] Key stacking is just like a label. [40:33.860 --> 40:38.620] I'm sure this has been done before a million times because it's really not that complicated. [40:39.260 --> 40:40.780] It's pretty simple in practice. [40:40.780 --> 40:42.060] And we'll see that in a minute. [40:42.060 --> 40:46.620] But essentially key stacking is the practice of combining the results of multiple keying [40:46.620 --> 40:48.620] methods to create a single combined keys. [40:48.800 --> 40:55.100] So for example, let's say we want a key that's combined of four parts. [40:55.100 --> 40:58.860] The hard drive serial number, external IP address, a non-stored in the payload file, [40:58.860 --> 41:03.720] so it's a stored component, and also a one-time key that is retrieved over HTTPS. [41:03.940 --> 41:07.580] Well, in that point, we essentially would just make four method calls within our payload. [41:09.040 --> 41:13.380] To four different key derivation functions, concatenate the results together. [41:13.540 --> 41:19.400] And by doing that, we'd have one encryption key that was derived from all these different [41:19.400 --> 41:20.220] sources. [41:20.440 --> 41:23.100] So one advantage of doing this is it gives us a little more security. [41:23.100 --> 41:25.080] It's difficult to compromise. [41:25.600 --> 41:27.700] Disadvantage is kind of complicated. [41:27.700 --> 41:32.420] If you do this by hand, it's just adding more moving parts to the equation. [41:32.420 --> 41:37.100] But once again, since we're using a framework, it makes it a little less complicated. [41:40.140 --> 41:45.380] Essentially, what makes this possible is that the actual architecture that we saw at [41:45.380 --> 41:47.820] the very beginning, it has been updated a little bit. [41:47.820 --> 41:51.660] So remember, originally, we just had that shellcode runner and a payload main in there [41:51.660 --> 41:54.780] and an executor function. [41:54.780 --> 41:56.600] In this case, we still have our shellcode runner. [41:56.600 --> 41:57.720] It's our outermost wrapper. [41:57.720 --> 42:02.320] That's our LulzBot-specific script that encapsulates everything. [42:02.420 --> 42:04.120] But we also have our payload main. [42:05.760 --> 42:09.860] And within that, we now have, you see here, we all have all these D-key functions. [42:11.080 --> 42:14.160] So we have a D-key 1, D-key 2, all the way through D-key N. [42:14.160 --> 42:15.960] It's an arbitrary number of D-key functions. [42:16.640 --> 42:23.560] And essentially, the way that this works is that each key part is extracted from each [42:23.560 --> 42:28.460] of these key derivation functions and passed to the decryptor function along with the [42:28.460 --> 42:34.840] shellcode that combined or stacks keys is then used to get the plaintext shellcode and [42:34.840 --> 42:36.860] is passed to the executor. [42:36.960 --> 42:41.280] So really, it's not too bad. [42:43.860 --> 42:45.920] We already went over key stacking. [42:46.820 --> 42:48.580] So let's talk about pre-modules and post-modules. [42:48.580 --> 42:51.980] And I included the cookie monster here, because who doesn't like the cookie monster? [42:56.500 --> 42:58.440] So what are pre-modules and post-modules? [43:00.280 --> 43:01.740] Essentially, this is a concept. [43:01.740 --> 43:08.020] I mean, there's often when you're executing that initial access payload, right, that shellcode [43:08.020 --> 43:13.480] within your shellcode runner, there are things that you want to do first before you actually [43:13.480 --> 43:16.240] start trying to execute your shellcode. [43:16.620 --> 43:20.440] For one thing, you might want to perform sandbox checks, like if you're trying to see if you're [43:20.440 --> 43:27.460] in one of those automated sandboxes, you might want to check for some node attributes of [43:27.460 --> 43:34.020] the sandboxes, such as certain file paths or number of CPUs or what have you, to actually [43:34.020 --> 43:39.840] see if you're in a quote-unquote real environment or in a sandbox. [43:41.120 --> 43:44.380] Also, we mentioned that this is likely going to be going through the CLR. [43:44.420 --> 43:48.200] So you might want to try to bypass AMSI, and that's something that you might want to try [43:48.200 --> 43:53.060] to do before you execute your shellcode. [43:54.380 --> 44:00.940] So what pre-modules do, essentially, they are just subroutines that are pre-pended to [44:00.940 --> 44:02.160] everything else in your payload. [44:02.160 --> 44:06.040] So what DropEngine lets you do is you can specify any number of pre-modules that you [44:06.040 --> 44:09.500] want, and these will just get run before everything else does. [44:10.440 --> 44:15.140] So, for example, if you want to run a sandbox check and an AMSI bypass, you pass those both [44:15.760 --> 44:23.040] to DropEngine as pre-modules, they then get executed, and then once they finish executing, [44:23.540 --> 44:26.240] and they are executed in the order that you specify them, by the way, which is pretty [44:26.240 --> 44:29.080] cool because you actually control which order they execute in. [44:29.080 --> 44:33.020] But once they finish executing, then we execute the rest of your shellcode here. [44:35.180 --> 44:37.400] So post-modules, they're pretty much the opposite thing. [44:37.400 --> 44:42.240] Instead of being pre-pended to the beginning of the payload, we append them to the end [44:42.240 --> 44:42.820] of the payload. [44:42.820 --> 44:49.420] So that's useful for if there's something that you want to do after your shellcode terminates. [44:49.420 --> 44:56.740] So cleanup routines, log file deletion, modification, and both pre-modules and post-modules [44:56.740 --> 45:00.480] should be completely modular and mutable, just like the rest of the payload's components. [45:00.480 --> 45:07.060] So you can mangle all the string names and variable names, however you want. [45:09.790 --> 45:16.930] And so if we're going to demo the process of adding pre-modules, here's how you do it. [45:18.490 --> 45:20.610] I'll make this a super fast one. [45:30.060 --> 45:36.880] So for example, here, you can see if we want to create a payload that, let's say we want [45:36.880 --> 45:43.500] to run an empty sandbox check, say like check to see if we're in a sandbox by checking the [45:43.500 --> 45:46.040] minimum number of USBs that have ever been installed. [45:48.580 --> 45:53.880] Let's say we look for also file paths that can deliver us to the event that we're in [45:53.920 --> 45:54.520] a sandbox. [45:54.520 --> 45:57.140] A file path is a sandbox check. [45:57.140 --> 46:01.960] Then finally, we want to execute an empty scan buffer bypass. [46:02.560 --> 46:05.780] We can just append these here as pre-modules. [46:17.880 --> 46:34.250] And actually, if you're curious what this looks like, I'm not actually going to save [46:34.250 --> 46:34.490] this. [46:34.490 --> 46:36.090] I'm just going to send it to the screen. [46:38.130 --> 46:39.430] Yeah, that's what I want to do. [46:39.430 --> 46:43.830] And then I'm going to use that really, really small shellcode that I showed you earlier. [46:43.910 --> 46:45.230] It's easier to read. [46:48.360 --> 46:52.120] It should not be from the exclusion folder, because that small shellcode is not in the [46:52.120 --> 46:53.140] exclusion folder. [46:57.340 --> 47:05.840] And you'll see here that, you know, here are your sandbox checks and your empty bypass, [47:05.840 --> 47:08.040] and that's all getting executed up here, essentially. [47:08.040 --> 47:11.780] So that all gets done right before you run everything else. [47:12.360 --> 47:16.640] So once again, let's get up on our MSVL payload. [47:16.640 --> 47:21.100] We're going to start up our handler, and we created it in the last step, so I'm not going [47:21.100 --> 47:22.120] to recreate it. [47:23.580 --> 47:27.520] And you see that it runs, so everything just kind of goes swimmingly, because we're [47:27.520 --> 47:28.400] out of the sandbox. [47:31.440 --> 47:32.700] We go ahead and fill this... [47:39.470 --> 47:41.330] PowerPoint, just wrap this up. [47:50.750 --> 47:53.530] We kind of did both demos at once, and that's all right. [47:53.770 --> 47:56.890] The last thing we're going to talk about is, essentially, how do you create DropEngine [47:56.890 --> 47:57.450] modules? [47:57.450 --> 48:02.510] So the goal of the project isn't really to provide pre-baked methods for bypassing APADDR. [48:04.650 --> 48:05.810] It's really more... [48:06.770 --> 48:12.890] We did provide some example modules, but really, they're not really doing anything new or novel. [48:12.950 --> 48:17.570] And this is by design, because the goal of this framework is to enable red teams to maximize [48:17.570 --> 48:20.910] the value that they get from their individual payloads by converting them into reusable [48:20.910 --> 48:21.950] modules. [48:22.010 --> 48:25.810] And if you're a defender, this is useful, too, because you can use this tool to quickly [48:25.810 --> 48:29.850] create large sets of sample payloads from which to build a learning strategy. [48:32.010 --> 48:35.630] So there are two types of modules that you can build, input modules and output modules. [48:35.750 --> 48:38.910] Essentially, input modules are anything that's going in before it hits your payload. [48:38.910 --> 48:45.310] So your encryption function is an input module, whereas, for example, your executor function [48:45.310 --> 48:46.570] is going to be an output module. [48:46.890 --> 48:48.430] This is super important. [48:48.570 --> 48:55.910] Shout out to Marcelo, my leader, because basically the loader that he's using to build these [48:55.910 --> 48:59.510] is heavily based off of some of the stuff he's done. [49:01.630 --> 49:05.110] When I think about input modules, they always have to correspond to one or more matching [49:05.110 --> 49:06.230] output modules. [49:06.490 --> 49:08.750] But they're relatively simple to implement. [49:08.750 --> 49:14.430] As you can see here, what we're doing is we're building an encryption key module. [49:14.430 --> 49:19.630] And we're just inheriting from this base class and then creating a constructor, which is [49:19.630 --> 49:22.490] just kind of setting the various attributes associated with this. [49:24.130 --> 49:26.350] All the argument handling is up on the back end. [49:26.350 --> 49:30.150] If you want to pass command line arguments to your module, you just add an add arguments [49:30.150 --> 49:30.590] function. [49:30.590 --> 49:35.370] If you've ever used parse in Python before, you can just add all these here. [49:35.370 --> 49:39.790] The parser is already initialized by one of the parent classes of your module. [49:40.030 --> 49:44.130] So you can just make calls to self.parse.addArgument and add all the arguments you want. [49:44.130 --> 49:48.690] And that will get parsed automatically, essentially, once your payload is generated. [49:49.050 --> 49:50.230] And then you have your generate routine. [49:50.230 --> 49:50.830] And this is essentially... [49:51.970 --> 49:55.030] Well, for encryption keys, it's generate, but depending on the module type you're using, [49:55.030 --> 49:57.890] you're going to have your function that actually does stuff. [49:58.590 --> 50:02.490] Output modules, very similar, but even simpler. [50:02.650 --> 50:05.830] So the way the output modules work, this is the actual... [50:06.990 --> 50:09.250] These actually get rendered into your payload. [50:09.710 --> 50:12.410] They may potentially correspond to an input module. [50:12.410 --> 50:15.870] They may not, as in the case of an executor, for example. [50:15.990 --> 50:18.530] But it's really just a simple two-component design. [50:18.530 --> 50:24.810] You have a Jinja template and a Python file that stores metadata that is passed to the Jinja template. [50:25.430 --> 50:28.910] So, for example, here I've got a list of all my variables and imports and whatnot. [50:29.450 --> 50:34.690] And that gets passed to the interface, then passed back, and then loaded into the template in [50:34.690 --> 50:36.570] however format you need it. [50:36.770 --> 50:40.030] And then here you just have the Jinja template that you're using. [50:41.170 --> 50:45.910] As far as actually creating these things go, how much time do we actually have? [50:46.870 --> 50:48.510] I won't spend too much time on this. [50:52.310 --> 50:55.550] And it's just that if you want to create one of these modules, aside from the stuff... [50:55.550 --> 50:57.530] I guess what we haven't really shown you is the template. [50:57.650 --> 51:00.990] But here's just an example module. [51:01.170 --> 51:02.450] It doesn't really do anything. [51:04.550 --> 51:08.710] But see, all that you have to do is just set these attributes, and then you give it a list [51:08.710 --> 51:13.010] of interfaces it's compatible with, and then any input modules it's compatible with. [51:13.170 --> 51:18.530] Give it a list of all the variables in your C-sharp file, or whatever kind of file you're using. [51:18.530 --> 51:20.530] Really, it's not limited to C-sharp. [51:20.570 --> 51:24.490] And then also give it the name of a template, and give it a function and class name. [51:25.270 --> 51:27.510] In this particular instance, you have to do that. [51:28.950 --> 51:30.090] It's not very long. [51:30.770 --> 51:32.410] Then you have to create a template. [51:33.350 --> 51:35.550] And so, literally, this is the process of creating a template. [51:35.550 --> 51:37.890] And I'm actually working on automating this. [51:38.530 --> 51:41.710] But that requires, essentially, you need to write something that can parse C-sharp. [51:41.710 --> 51:44.390] And that's coming along, but it's not quite done yet. [51:44.390 --> 51:49.790] But for now, what you do, if you want to actually turn just a normal C-sharp file into [51:50.790 --> 51:55.210] a template that can be understood by DropEngine, you just find all your variables in here, [51:55.210 --> 51:57.550] and just wrap them in this Jinja parameter. [51:57.550 --> 52:01.430] So you just say d, and then you use a syntax here. [52:01.430 --> 52:03.690] So we've got variable nick. [52:05.650 --> 52:07.470] We just kind of edit it like that. [52:08.450 --> 52:12.210] And then we can do the same thing here with variable n. [52:13.030 --> 52:14.810] It should be our only two variables there. [52:15.790 --> 52:17.630] And I just do that once again over here. [52:20.790 --> 52:25.690] This is going to be painful for longer ones, but, you know, you only have to do it once in that case. [52:26.030 --> 52:31.250] And I'm working on some ways to kind of automate a lot of that. [52:33.810 --> 52:34.530] Share screen... [52:34.530 --> 52:35.530] Back to PowerPoint... [52:40.140 --> 52:41.680] And that's pretty much it. [52:41.760 --> 52:42.380] I'm going to... [52:43.520 --> 52:46.700] Actually, this is a Zoom thing, so I don't really know. [52:46.940 --> 52:50.240] That's the location of the project on GitHub, if you want to check it out. [52:51.000 --> 52:51.700] I'm going to... [52:52.600 --> 52:56.560] I think it's supposed to be like a Q&A thing right now, and I need to figure out how that works. [52:56.620 --> 52:57.200] So I'm going to... [52:57.800 --> 53:03.540] Yeah, basically, once again, thank you so much for your time and for the presentation here. [53:03.540 --> 53:04.480] Excellent presentation. [53:04.480 --> 53:07.580] So for the Q&A, you can jump into Discord. [53:07.580 --> 53:09.160] It's going to be offline, of course. [53:09.160 --> 53:13.620] There's a little bit of delay between the stream and when they can answer. [53:13.840 --> 53:17.420] And there's a lot of people actually already talking about the presentation. [53:17.520 --> 53:18.740] So kudos. [53:19.500 --> 53:24.000] And for those of you also that probably just joined, [53:24.000 --> 53:27.660] please take a look at all the talks and all the activities that we have in our website. [53:27.660 --> 53:31.040] The description should be in the bottom of the screen, right? [53:31.040 --> 53:34.960] So in the description of the screen, all the links and related material. [53:34.960 --> 53:38.260] And also, please join the conversation, as we said, in Discord. [53:38.520 --> 53:43.560] So we're going to go in a little break, and the next presentation will start in just a few minutes. [53:43.560 --> 53:44.960] Thank you again, Gabriel.