1 00:00:00,690 --> 00:00:02,880 - So, coming up next is Wietze 2 00:00:02,880 --> 00:00:06,270 and he is a new speaker, so. 3 00:00:06,270 --> 00:00:07,103 - Lovely. 4 00:00:07,103 --> 00:00:08,100 Good morning, everyone. 5 00:00:08,100 --> 00:00:10,320 Welcome, you made it to the final day of "DEFCON". 6 00:00:10,320 --> 00:00:11,153 Woo! 7 00:00:12,390 --> 00:00:14,250 I'm here to kick-off track three this morning 8 00:00:14,250 --> 00:00:16,860 and I'll be talking about DLL hijacking 9 00:00:16,860 --> 00:00:18,900 and how you can make that even more fun 10 00:00:18,900 --> 00:00:21,249 with environment variables. 11 00:00:21,249 --> 00:00:22,082 (smacks lips) 12 00:00:22,082 --> 00:00:23,340 So, quickly, introduce myself. 13 00:00:23,340 --> 00:00:25,020 So, my name is Wietze. 14 00:00:25,020 --> 00:00:25,980 That's a Dutch name, 15 00:00:25,980 --> 00:00:28,230 but I, currently, live in London in UK, 16 00:00:28,230 --> 00:00:29,850 where I work for "CrowdStrike" 17 00:00:29,850 --> 00:00:31,440 as part of the "OverWatch Elite Team" 18 00:00:31,440 --> 00:00:33,240 as a senior threat hunter. 19 00:00:33,240 --> 00:00:34,560 I have, previously, presented 20 00:00:34,560 --> 00:00:36,240 at some other conferences before, 21 00:00:36,240 --> 00:00:38,940 amongst other things about DLL hijacking 22 00:00:38,940 --> 00:00:40,020 and yeah, as I was saying, 23 00:00:40,020 --> 00:00:41,100 today, I will be talking 24 00:00:41,100 --> 00:00:44,370 about how you can do that with environment variables. 25 00:00:44,370 --> 00:00:46,680 So, in order to get there, 26 00:00:46,680 --> 00:00:49,767 I'm gonna give a quick recap of DLL hijacking 27 00:00:49,767 --> 00:00:52,410 and the variants, you may be familiar with. 28 00:00:52,410 --> 00:00:55,830 Then, I'll give a quick intro on environment variables 29 00:00:55,830 --> 00:00:57,390 and then, later on, we're gonna bring them together 30 00:00:57,390 --> 00:00:59,373 and do some really cool stuff. 31 00:01:00,315 --> 00:01:01,148 (smacks lips) 32 00:01:01,148 --> 00:01:02,700 So, let's crack on. 33 00:01:02,700 --> 00:01:04,530 DLL hijacking. 34 00:01:04,530 --> 00:01:07,170 There's a couple of different definitions for that. 35 00:01:07,170 --> 00:01:09,600 So, I thought, before I start, I might give you mine, 36 00:01:09,600 --> 00:01:11,580 so, we're all clear what I mean by that. 37 00:01:11,580 --> 00:01:14,970 So, to me, DLL hijacking is the tricking 38 00:01:14,970 --> 00:01:19,470 of a legitimate or trusted, assigned executable 39 00:01:19,470 --> 00:01:21,750 into loading an arbitrary DLL. 40 00:01:21,750 --> 00:01:23,310 So, there are multiple ways of doing that. 41 00:01:23,310 --> 00:01:26,160 But in essence, as you can see here on the diagram, 42 00:01:26,160 --> 00:01:27,750 you have a trusted program, 43 00:01:27,750 --> 00:01:30,570 it, normally, loads your libraries, the DLLs 44 00:01:30,570 --> 00:01:34,710 and somehow, you trick that into loading an evil DLL, right? 45 00:01:34,710 --> 00:01:37,380 So, from an offensive perspective, that is great. 46 00:01:37,380 --> 00:01:39,570 Because you don't have to run your own executable. 47 00:01:39,570 --> 00:01:43,500 You can leverage the reputation of the trusted program 48 00:01:43,500 --> 00:01:44,790 that allows you to, 49 00:01:44,790 --> 00:01:46,980 if you have a really dumb "AV" to get away with it, 50 00:01:46,980 --> 00:01:49,800 or if you have "EDR" to make it look a lot more legitimate 51 00:01:49,800 --> 00:01:51,123 than it, actually, is. 52 00:01:52,860 --> 00:01:54,990 As I was saying, there's multiple variants 53 00:01:54,990 --> 00:01:57,750 and these are the most common ones. 54 00:01:57,750 --> 00:02:00,700 I think, most of you may be familiar with DLL side-loading. 55 00:02:01,680 --> 00:02:03,150 That is very simple one. 56 00:02:03,150 --> 00:02:05,700 You, basically, have a vulnerable executable 57 00:02:05,700 --> 00:02:08,520 that loads DLLs in an unspecified way. 58 00:02:08,520 --> 00:02:12,030 It doesn't specify the full path, but a relative path. 59 00:02:12,030 --> 00:02:14,640 If you, then, move the vulnerable executable 60 00:02:14,640 --> 00:02:16,980 to an attacker-writable folder, 61 00:02:16,980 --> 00:02:19,920 you put it next to a malicious DLL and you're executed, 62 00:02:19,920 --> 00:02:22,920 it will allow you to run your malicious code, 63 00:02:22,920 --> 00:02:25,200 via this trusted program. 64 00:02:25,200 --> 00:02:26,760 So, yeah, DLL side-loading, 65 00:02:26,760 --> 00:02:29,100 I think, is by far, the most common one. 66 00:02:29,100 --> 00:02:32,430 Another one is DLL search order hijacking. 67 00:02:32,430 --> 00:02:35,040 I think, these two are often confused, to be honest. 68 00:02:35,040 --> 00:02:36,960 They, both, leverage the search order. 69 00:02:36,960 --> 00:02:39,450 But to me, DLL search order hijacking, 70 00:02:39,450 --> 00:02:42,907 is when you leave the executable in its original place, 71 00:02:42,907 --> 00:02:44,757 "Program files", "System32", 72 00:02:45,720 --> 00:02:47,130 but if it is vulnerable, 73 00:02:47,130 --> 00:02:49,830 it means that you can put a DLL in a location 74 00:02:49,830 --> 00:02:52,920 that is searched before the actual DLL. 75 00:02:52,920 --> 00:02:53,890 And that means, 76 00:02:53,890 --> 00:02:56,284 you are, literally, hijacking the search order. 77 00:02:56,284 --> 00:02:57,950 (smacks lips) These are much rarer, I think, 78 00:02:57,950 --> 00:02:59,580 than most people think they are. 79 00:02:59,580 --> 00:03:02,250 So, there's a couple of good candidates there, 80 00:03:02,250 --> 00:03:06,000 but there's way, way more DLL side-loading candidates. 81 00:03:06,000 --> 00:03:09,540 So, yeah, they're related, but distinct techniques 82 00:03:09,540 --> 00:03:11,440 and I think, these are often confused. 83 00:03:12,300 --> 00:03:15,120 DLL substitution is one you, really, shouldn't forget about. 84 00:03:15,120 --> 00:03:16,200 It's super simple, right? 85 00:03:16,200 --> 00:03:20,310 Just replace the legitimate DLL with a bad one. 86 00:03:20,310 --> 00:03:21,750 If you remember (indistinct), 87 00:03:21,750 --> 00:03:24,630 this was, literally, part of the attacker path. 88 00:03:24,630 --> 00:03:28,290 They replaced a legitimate DLL in "System32" 89 00:03:28,290 --> 00:03:29,640 with a malicious one 90 00:03:29,640 --> 00:03:31,620 and the malicious one inserted extra commands 91 00:03:31,620 --> 00:03:34,590 for the industrial control system. 92 00:03:34,590 --> 00:03:36,600 So, it is DLL hijacking, right? 93 00:03:36,600 --> 00:03:37,710 Maybe, not super novel, 94 00:03:37,710 --> 00:03:40,713 but you are hijacking a legitimate application. 95 00:03:41,790 --> 00:03:43,590 So, these are really common. 96 00:03:43,590 --> 00:03:45,720 I wanna, quickly, touch on three less-common ones, 97 00:03:45,720 --> 00:03:48,363 which, again, are all types of DLL hijacking. 98 00:03:49,230 --> 00:03:51,900 You may have heard of phantom DLL hijacking. 99 00:03:51,900 --> 00:03:55,410 So, this is when an application tries to load a DLL 100 00:03:55,410 --> 00:03:57,460 that doesn't exist at all. 101 00:03:57,460 --> 00:03:58,293 (smacks lips) 102 00:03:58,293 --> 00:04:00,390 So, in which case, you can just put the DLL, 103 00:04:00,390 --> 00:04:04,800 anywhere on the search order and it will load your DLL. 104 00:04:04,800 --> 00:04:06,150 So, that's a really simple one. 105 00:04:06,150 --> 00:04:08,550 And again, very few candidates, 106 00:04:08,550 --> 00:04:10,410 but if you have a good candidate, 107 00:04:10,410 --> 00:04:13,320 it can, sometimes, lead to privilege escalation, 108 00:04:13,320 --> 00:04:16,402 or what, pop-up assistance. 109 00:04:16,402 --> 00:04:17,235 (smacks lips) 110 00:04:17,235 --> 00:04:20,250 There's, also, something called "Windows SxS Hijacking", 111 00:04:20,250 --> 00:04:22,560 or "Windows Side-by-Side Hijacking". 112 00:04:22,560 --> 00:04:24,450 I think, in the past, this was really confusing, 113 00:04:24,450 --> 00:04:26,400 because it has the word "Side" in it. 114 00:04:26,400 --> 00:04:29,100 So, people thought, "Oh, this is DLL side-loading." 115 00:04:29,100 --> 00:04:31,710 I've, only, ever seen one documented case. 116 00:04:31,710 --> 00:04:34,080 Again, I don't think it's as prevalent 117 00:04:34,080 --> 00:04:35,100 as some people think it is. 118 00:04:35,100 --> 00:04:37,770 So, it's, basically, relying 119 00:04:37,770 --> 00:04:39,690 on a specific technique in "Windows", 120 00:04:39,690 --> 00:04:42,750 called the "Windows Side-by-Side" and hijacking it that way. 121 00:04:42,750 --> 00:04:43,583 But again, 122 00:04:43,583 --> 00:04:45,900 I've, only, ever seen one proper documented case. 123 00:04:45,900 --> 00:04:49,380 And finally, a wider class, input-based hijacking. 124 00:04:49,380 --> 00:04:52,800 This is when you manipulate a registry key or a command line 125 00:04:52,800 --> 00:04:57,120 and in that way, manage to load a malicious DLL. 126 00:04:57,120 --> 00:04:58,860 So, I think, "Firefox", for example, 127 00:04:58,860 --> 00:05:00,147 still has an executable, 128 00:05:00,147 --> 00:05:01,080 but if you run it 129 00:05:01,080 --> 00:05:04,770 and if you specify a custom path on the command line, 130 00:05:04,770 --> 00:05:06,570 it will just load DLLs from that folder. 131 00:05:06,570 --> 00:05:09,660 So, you get a trusted "Mozilla" executable 132 00:05:09,660 --> 00:05:11,944 and it will load the malicious DLL. 133 00:05:11,944 --> 00:05:12,780 (smacks lips) 134 00:05:12,780 --> 00:05:14,550 So, that's all great, right? 135 00:05:14,550 --> 00:05:16,590 So, six types of DLL hijacking. 136 00:05:16,590 --> 00:05:18,900 This has been around for a while now, for years 137 00:05:18,900 --> 00:05:21,390 and there have been many great blogs and tools 138 00:05:21,390 --> 00:05:24,900 that can help you explain what it is, leverage it yourself 139 00:05:24,900 --> 00:05:26,370 and as a result, 140 00:05:26,370 --> 00:05:28,410 we have very well-documented techniques 141 00:05:28,410 --> 00:05:29,820 that are very well-researched, 142 00:05:29,820 --> 00:05:32,124 but also very well-detected. 143 00:05:32,124 --> 00:05:32,957 (smacks lips) 144 00:05:32,957 --> 00:05:34,440 It just means that if you do this, 145 00:05:34,440 --> 00:05:37,740 again, you might trick, really, basic "AV" and "EDR", 146 00:05:37,740 --> 00:05:40,800 but it's less and less likely that you'll get away with it. 147 00:05:40,800 --> 00:05:42,600 So, that begs the question, 148 00:05:42,600 --> 00:05:43,830 if there is something we can do 149 00:05:43,830 --> 00:05:45,960 to, still, have DLL hijacking, right? 150 00:05:45,960 --> 00:05:49,740 So, still, leveraging the reputation of a trusted program, 151 00:05:49,740 --> 00:05:52,173 but do it in a better or more stealthy way. 152 00:05:53,225 --> 00:05:54,058 (smacks lips) 153 00:05:54,058 --> 00:05:56,130 So, that is where environment variables come in. 154 00:05:56,130 --> 00:06:00,240 And as I said, before I go straight into the hijacking bit, 155 00:06:00,240 --> 00:06:01,140 a bit of background, 156 00:06:01,140 --> 00:06:02,220 so, we're all on the same page 157 00:06:02,220 --> 00:06:04,350 as to what environment variables are 158 00:06:04,350 --> 00:06:06,783 and why we have them in the first place. 159 00:06:09,030 --> 00:06:10,500 Right, environment variables. 160 00:06:10,500 --> 00:06:11,520 You may have heard of them. 161 00:06:11,520 --> 00:06:13,680 If you use "Linux" or Unix-based systems, 162 00:06:13,680 --> 00:06:17,880 you, probably, will use them very often. 163 00:06:17,880 --> 00:06:20,850 It's, basically, a variable or a dynamic variable 164 00:06:20,850 --> 00:06:22,980 that can be used by running programs. 165 00:06:22,980 --> 00:06:25,350 So, as well as, already alluding to 166 00:06:25,350 --> 00:06:27,840 on "Linux" and Unix-based systems, 167 00:06:27,840 --> 00:06:31,107 these are very prevalent in the shells, right? 168 00:06:31,107 --> 00:06:31,980 (smacks lips) 169 00:06:31,980 --> 00:06:34,620 You may know in the shells on "Linux", 170 00:06:34,620 --> 00:06:36,870 you get the dollar sign and then, the variable name 171 00:06:36,870 --> 00:06:39,720 and that allows you in scripts, in your terminal 172 00:06:39,720 --> 00:06:41,700 to set a variable once 173 00:06:41,700 --> 00:06:45,030 and then, just leverage it in a script or elsewhere 174 00:06:45,030 --> 00:06:47,130 and it can just leverage that value. 175 00:06:47,130 --> 00:06:49,020 So, it's like a global variable, right, 176 00:06:49,020 --> 00:06:51,930 if you ever done a programming. 177 00:06:51,930 --> 00:06:53,790 In "Windows", you've got this, too. 178 00:06:53,790 --> 00:06:54,750 In the "Command Prompt", 179 00:06:54,750 --> 00:06:56,610 you can set an environment variable 180 00:06:56,610 --> 00:06:59,940 and you leverage it using percentage sign. 181 00:06:59,940 --> 00:07:04,940 So, you've got "%VAR%" to get the variable contents. 182 00:07:05,760 --> 00:07:07,020 What you would almost forget, 183 00:07:07,020 --> 00:07:09,510 is that processes can also leverage it, alright? 184 00:07:09,510 --> 00:07:12,810 So, you, typically, may use it just in a shell, 185 00:07:12,810 --> 00:07:15,300 but any process can call, 186 00:07:15,300 --> 00:07:18,120 for example, from "C", you can call the function "getenv" 187 00:07:18,120 --> 00:07:18,953 with the variable name 188 00:07:18,953 --> 00:07:20,280 and it would give you the value 189 00:07:20,280 --> 00:07:22,350 that it will set to, in your environment. 190 00:07:22,350 --> 00:07:25,020 'Cause after all, an environment is like your system, right, 191 00:07:25,020 --> 00:07:25,920 or your shell. 192 00:07:25,920 --> 00:07:28,713 So, it's in the scope of your system. 193 00:07:30,000 --> 00:07:31,980 Again, it's quite an old technique, 194 00:07:31,980 --> 00:07:33,270 I'll touch on that on the next slide, 195 00:07:33,270 --> 00:07:35,490 but it's all stored as a string, 196 00:07:35,490 --> 00:07:38,340 typically, an "ASCII" string, even. 197 00:07:38,340 --> 00:07:41,100 So, you can put integers and booleans in there, of course, 198 00:07:41,100 --> 00:07:43,860 but you would have to convert them or cast them yourself. 199 00:07:43,860 --> 00:07:45,510 It's, basically, always a string. 200 00:07:47,700 --> 00:07:48,533 Right. 201 00:07:48,533 --> 00:07:51,120 So, I don't mean to turn this into a proper history lesson, 202 00:07:51,120 --> 00:07:52,647 but just a bit of background 203 00:07:52,647 --> 00:07:54,510 to, again, understand why we have them 204 00:07:54,510 --> 00:07:57,990 and why we still have them in 2022, environment variables. 205 00:07:57,990 --> 00:08:02,550 So, the first mainstream "OS" to have them, was "Unix V7". 206 00:08:02,550 --> 00:08:04,080 So, they were the first mainstream "OS" 207 00:08:04,080 --> 00:08:05,760 to come up with this concept. 208 00:08:05,760 --> 00:08:09,360 So, they didn't have to bug program users 209 00:08:09,360 --> 00:08:11,580 to ask every time, like, "What is your username, 210 00:08:11,580 --> 00:08:12,900 what is your home path?" 211 00:08:12,900 --> 00:08:15,030 Instead, you just define it once, 212 00:08:15,030 --> 00:08:16,710 you run a script or program 213 00:08:16,710 --> 00:08:19,500 and it would know what your username was. 214 00:08:19,500 --> 00:08:21,120 So, very simple. 215 00:08:21,120 --> 00:08:22,680 First time was in the late seventies 216 00:08:22,680 --> 00:08:25,027 and then, only a few years later, 217 00:08:25,027 --> 00:08:28,230 "PC-DOS 2.0", also, included it, 218 00:08:28,230 --> 00:08:30,630 same technology, in the shell, 219 00:08:30,630 --> 00:08:32,670 you could define the variables. 220 00:08:32,670 --> 00:08:35,130 So, you could, probably, not see it at the very back, 221 00:08:35,130 --> 00:08:37,680 but I got a little excerpt of the documentation, 222 00:08:37,680 --> 00:08:41,100 which, basically, sums up what it does. 223 00:08:41,100 --> 00:08:44,220 So, it's, basically, saying, it's a dynamic variable, 224 00:08:44,220 --> 00:08:46,560 it will be replaced in the script if you use it 225 00:08:46,560 --> 00:08:49,500 and you can use the set command to give it a name 226 00:08:49,500 --> 00:08:52,606 and then, a value and then, you can leverage that. 227 00:08:52,606 --> 00:08:53,550 (smacks lips) 228 00:08:53,550 --> 00:08:54,383 Right. 229 00:08:54,383 --> 00:08:55,987 Then, early nineties 230 00:08:55,987 --> 00:08:59,880 "Windows 3.1" introduces the "Windows Registry". 231 00:08:59,880 --> 00:09:01,440 So, if you've ever used "Windows", 232 00:09:01,440 --> 00:09:02,970 you will be familiar with it. 233 00:09:02,970 --> 00:09:06,390 It's like the central settings hive 234 00:09:06,390 --> 00:09:07,860 that you use in "Windows". 235 00:09:07,860 --> 00:09:10,110 And I think, this is quite a pivotal moment 236 00:09:10,110 --> 00:09:11,550 for environment variables, 237 00:09:11,550 --> 00:09:14,040 because when you really think about it, 238 00:09:14,040 --> 00:09:16,800 environment variables are supposed to store information 239 00:09:16,800 --> 00:09:18,213 that programs can use. 240 00:09:19,177 --> 00:09:21,480 "Windows Registry" does pretty much the same, right? 241 00:09:21,480 --> 00:09:25,200 It stores all sorts of system-level configuration settings, 242 00:09:25,200 --> 00:09:27,650 as well as, program-level configuration settings. 243 00:09:28,740 --> 00:09:31,380 But we'll see later, environment variables, nowaday, 244 00:09:31,380 --> 00:09:33,240 live in the registry. 245 00:09:33,240 --> 00:09:35,760 But I think, it's really interesting, 246 00:09:35,760 --> 00:09:38,250 because we, still, have registry, 247 00:09:38,250 --> 00:09:40,560 oh, sorry, we, still, have environment variables. 248 00:09:40,560 --> 00:09:41,790 But if you think about it, 249 00:09:41,790 --> 00:09:43,920 you could, really, only, have the "Windows Registry" 250 00:09:43,920 --> 00:09:47,531 and not need environment variables in "Windows", at all. 251 00:09:47,531 --> 00:09:48,364 (smacks lips) 252 00:09:48,364 --> 00:09:49,197 Cool. 253 00:09:49,197 --> 00:09:52,290 Then, very quickly, end of the century, 254 00:09:52,290 --> 00:09:55,710 we had, already, lots of security, vulnerability researches, 255 00:09:55,710 --> 00:09:58,897 identifying issues with environment variables. 256 00:09:58,897 --> 00:10:01,320 "Windows" defines a couple of them out-of-the-box. 257 00:10:01,320 --> 00:10:04,560 And for example, the "PATH" environment variable, 258 00:10:04,560 --> 00:10:05,640 which you may have heard of 259 00:10:05,640 --> 00:10:07,470 and it caused lots of trouble, 260 00:10:07,470 --> 00:10:08,940 lots of vulnerabilities, there. 261 00:10:08,940 --> 00:10:12,267 So, the earliest I could find, was from 1997, 262 00:10:12,267 --> 00:10:14,400 was some sys admin complaining about it, 263 00:10:14,400 --> 00:10:17,193 not implementing security, properly. 264 00:10:18,630 --> 00:10:19,463 And this person said, 265 00:10:19,463 --> 00:10:21,630 "Why would other application developers bother 266 00:10:21,630 --> 00:10:24,150 to support secure configurations 267 00:10:24,150 --> 00:10:26,340 if this is what they see coming out of 'Redmond'?" 268 00:10:26,340 --> 00:10:27,780 So, he was, clearly, not happy 269 00:10:27,780 --> 00:10:29,430 and well, we will find out later 270 00:10:29,430 --> 00:10:33,150 what other people in "Redmond" did about this vulnerability. 271 00:10:33,150 --> 00:10:34,200 And then, finally, 272 00:10:34,200 --> 00:10:35,910 at the end of the century as well, in 1999, 273 00:10:35,910 --> 00:10:38,100 the first ever CVEs were issued. 274 00:10:38,100 --> 00:10:40,230 And the first batch, actually, included, 275 00:10:40,230 --> 00:10:41,063 I think, it's two, 276 00:10:41,063 --> 00:10:44,850 but at least one environment variable-based security issue 277 00:10:44,850 --> 00:10:47,188 that (indistinct) privilege escalation. 278 00:10:47,188 --> 00:10:48,021 (smacks lips) Right? 279 00:10:48,021 --> 00:10:49,320 So, this was, like, in one minute, 280 00:10:49,320 --> 00:10:51,660 the history of environment variables. 281 00:10:51,660 --> 00:10:52,493 But let's again, 282 00:10:52,493 --> 00:10:55,260 now, look at what that looks like in "Windows". 283 00:10:55,260 --> 00:10:57,180 So, funnily enough, 284 00:10:57,180 --> 00:11:00,270 you can define as many environment variables as you want. 285 00:11:00,270 --> 00:11:01,440 But there is an upper limit 286 00:11:01,440 --> 00:11:05,520 of the combination of variable names and values. 287 00:11:05,520 --> 00:11:08,850 So, any environment variables you define, 288 00:11:08,850 --> 00:11:11,910 are just stored in one massive concatenated string 289 00:11:11,910 --> 00:11:13,290 and this string, 290 00:11:13,290 --> 00:11:16,410 should not exceed two-to-the-power-15th minus one characters 291 00:11:16,410 --> 00:11:17,400 in total. 292 00:11:17,400 --> 00:11:19,140 So, whilst they give you some room, 293 00:11:19,140 --> 00:11:21,817 like, you can't put, like, proper programs, 294 00:11:21,817 --> 00:11:23,967 "Base64" encoded in there if you wanted to. 295 00:11:25,410 --> 00:11:26,730 As they already said, 296 00:11:26,730 --> 00:11:29,460 nowadays, the environment variables that you get 297 00:11:29,460 --> 00:11:30,870 when you start your computer, 298 00:11:30,870 --> 00:11:33,150 are stored in the "Windows Registry". 299 00:11:33,150 --> 00:11:35,677 So, what happens, if you start your computer? 300 00:11:35,677 --> 00:11:39,390 "Windows", like, the most parent process, basically, 301 00:11:39,390 --> 00:11:40,710 when you start your computer, 302 00:11:40,710 --> 00:11:44,160 looks up the system-level environment variables 303 00:11:44,160 --> 00:11:46,230 in this registry key, you see on screen, 304 00:11:46,230 --> 00:11:48,586 so, that lives in "HKEY_LOCAL_MACHINE". 305 00:11:48,586 --> 00:11:49,419 (smacks lips) 306 00:11:49,419 --> 00:11:51,780 These are the variables that apply to every user 307 00:11:51,780 --> 00:11:54,930 and all services and all service accounts. 308 00:11:54,930 --> 00:11:57,120 This is how your system is initialized. 309 00:11:57,120 --> 00:11:58,757 When you, then, log in, 310 00:11:58,757 --> 00:11:59,590 (smacks lips) 311 00:11:59,590 --> 00:12:02,130 it looks up the user-specific environment variables, 312 00:12:02,130 --> 00:12:04,130 which are stored in "HKEY_CURRENT_USER". 313 00:12:05,160 --> 00:12:07,470 There's also something called current session. 314 00:12:07,470 --> 00:12:09,030 I'm not, really, gonna talk about that today, 315 00:12:09,030 --> 00:12:10,890 but it, also, loads variables 316 00:12:10,890 --> 00:12:14,340 that are defined just for the duration of your session. 317 00:12:14,340 --> 00:12:15,173 Right? 318 00:12:15,173 --> 00:12:16,006 So, if you log in, 319 00:12:16,006 --> 00:12:18,660 you set an environment variable on that level, 320 00:12:18,660 --> 00:12:20,310 it will just live for that session. 321 00:12:20,310 --> 00:12:23,070 And as soon as you log off, it just disappears. 322 00:12:23,070 --> 00:12:23,910 And then, the final thing, 323 00:12:23,910 --> 00:12:25,230 which you would, almost, forget, 324 00:12:25,230 --> 00:12:28,770 is that environment variables live on process-level. 325 00:12:28,770 --> 00:12:30,660 So, you can define an environment variable 326 00:12:30,660 --> 00:12:33,690 that is only, active within a single process, 327 00:12:33,690 --> 00:12:37,290 but not its parents', not its siblings', just one process. 328 00:12:37,290 --> 00:12:38,810 So, what normally happens in "Windows", 329 00:12:38,810 --> 00:12:41,430 you start a new process, 330 00:12:41,430 --> 00:12:44,340 the environment variables that that new process has, 331 00:12:44,340 --> 00:12:47,070 are the same as its parents' environment variables. 332 00:12:47,070 --> 00:12:49,980 So, it just keeps passing down the environment variables 333 00:12:49,980 --> 00:12:51,600 and because it's quite an old technology 334 00:12:51,600 --> 00:12:54,603 and most software doesn't really use it, not really, 335 00:12:55,980 --> 00:12:58,530 it just passes down the values unchanged. 336 00:12:58,530 --> 00:13:01,620 So, you will have very consistent environment variables, 337 00:13:01,620 --> 00:13:02,453 across. 338 00:13:04,470 --> 00:13:06,280 So, if you know how processes work in "Windows", 339 00:13:06,280 --> 00:13:07,530 then, you might be familiar 340 00:13:07,530 --> 00:13:09,660 with the process environment block. 341 00:13:09,660 --> 00:13:13,320 This contains all sorts of information on the process. 342 00:13:13,320 --> 00:13:14,153 So, if you look, 343 00:13:14,153 --> 00:13:16,383 for example, at the process parameter struct, 344 00:13:17,220 --> 00:13:19,110 you see, lots of usual suspect, 345 00:13:19,110 --> 00:13:21,030 like, information you would expect for a process, 346 00:13:21,030 --> 00:13:25,143 like, the command line, standard in and out handles, 347 00:13:26,130 --> 00:13:27,210 current path. 348 00:13:27,210 --> 00:13:30,518 But there's, also, a block for environment variables. 349 00:13:30,518 --> 00:13:31,351 (smacks lips) 350 00:13:31,351 --> 00:13:33,030 And as you see here, this is from my demo lab. 351 00:13:33,030 --> 00:13:34,800 This is what you get out of the box 352 00:13:34,800 --> 00:13:35,790 when you install "Windows". 353 00:13:35,790 --> 00:13:37,290 So, this is "Windows 11". 354 00:13:37,290 --> 00:13:42,290 These are all, yeah, default, defined environment variables 355 00:13:42,450 --> 00:13:44,370 that programs might use 356 00:13:44,370 --> 00:13:47,310 to, for example, find out where your "AppData" folder is, 357 00:13:47,310 --> 00:13:49,590 or what your drive letter is, right? 358 00:13:49,590 --> 00:13:50,423 Normally, it's "C", 359 00:13:50,423 --> 00:13:52,110 but you can change it in the settings 360 00:13:52,110 --> 00:13:54,048 and then, your program might use that 361 00:13:54,048 --> 00:13:56,352 and change it accordingly. 362 00:13:56,352 --> 00:13:57,185 (smacks lips) 363 00:13:57,185 --> 00:13:59,024 But the interesting thing, again, maybe, you know it, 364 00:13:59,024 --> 00:14:01,110 but it didn't fully click, 365 00:14:01,110 --> 00:14:03,000 is that this exists on process-level. 366 00:14:03,000 --> 00:14:04,980 Every process has this massive list 367 00:14:04,980 --> 00:14:06,300 of environment variables. 368 00:14:06,300 --> 00:14:08,820 You can change it on process-level. 369 00:14:08,820 --> 00:14:11,545 So, if you look, for example, in the "Windows API", 370 00:14:11,545 --> 00:14:13,211 (smacks lips) this is one of the ways 371 00:14:13,211 --> 00:14:15,120 in which you can create a new process. 372 00:14:15,120 --> 00:14:15,953 You can see 373 00:14:15,953 --> 00:14:18,360 that you get the command line, application name, 374 00:14:18,360 --> 00:14:22,290 but you can, also, optionally, pass environment variables, 375 00:14:22,290 --> 00:14:23,370 custom environment variables. 376 00:14:23,370 --> 00:14:26,700 So, you can overwrite existing ones or add new ones 377 00:14:26,700 --> 00:14:29,190 and that allows you to, 378 00:14:29,190 --> 00:14:31,020 or allows the program to leverage them 379 00:14:31,020 --> 00:14:33,150 to, I don't know, find out a path, 380 00:14:33,150 --> 00:14:35,403 or find out your username, whatnot. 381 00:14:36,870 --> 00:14:38,190 So, that begs the question again, 382 00:14:38,190 --> 00:14:40,320 like, from a hacker's mindset, right? 383 00:14:40,320 --> 00:14:42,240 Is there, now, a scope for tampering? 384 00:14:42,240 --> 00:14:44,010 We've looked at DLL hijacking, 385 00:14:44,010 --> 00:14:45,720 we've looked at the environment variables, 386 00:14:45,720 --> 00:14:50,720 is there a way in which we can combine these two concepts? 387 00:14:50,940 --> 00:14:52,680 Because if you know environment variables, 388 00:14:52,680 --> 00:14:54,570 there's a couple of really interesting ones 389 00:14:54,570 --> 00:14:56,670 that are used quite often 390 00:14:56,670 --> 00:15:00,210 and they link to paths that you, normally, don't control. 391 00:15:00,210 --> 00:15:02,910 If you've just got foothold on a machine 392 00:15:02,910 --> 00:15:04,650 and you don't have admin permissions, 393 00:15:04,650 --> 00:15:07,830 you can't write to the "C:\Windows" folder, for example. 394 00:15:07,830 --> 00:15:10,860 So, the "SystemRoot" environment variable, 395 00:15:10,860 --> 00:15:14,580 which points to "C;\Windows", is an interesting one. 396 00:15:14,580 --> 00:15:16,530 Is there a way in which, on process-level, 397 00:15:16,530 --> 00:15:18,300 we could change this 398 00:15:18,300 --> 00:15:20,640 and maybe, trick a vulnerable executable 399 00:15:20,640 --> 00:15:23,160 into loading something that lives in a folder 400 00:15:23,160 --> 00:15:24,715 that I control? 401 00:15:24,715 --> 00:15:26,700 (smacks lips) So, it's the same with the system drive, 402 00:15:26,700 --> 00:15:28,230 or the "Windows" directory, 403 00:15:28,230 --> 00:15:31,200 which is, basically, an older version of the "SystemRoot" 404 00:15:31,200 --> 00:15:33,150 and same with the "Program Files" folders. 405 00:15:33,150 --> 00:15:34,830 So, if there are, still, applications, 406 00:15:34,830 --> 00:15:36,453 using environment variables, 407 00:15:37,346 --> 00:15:39,546 is there a scope for us to tamper with that? 408 00:15:40,800 --> 00:15:42,540 So, that's what how I started. 409 00:15:42,540 --> 00:15:45,510 So, basic concept, 410 00:15:45,510 --> 00:15:47,400 you pick an application, you wanna test 411 00:15:47,400 --> 00:15:48,780 to see if it's vulnerable, 412 00:15:48,780 --> 00:15:50,940 you update one of these environment variables 413 00:15:50,940 --> 00:15:52,080 that I was just talking about 414 00:15:52,080 --> 00:15:54,360 and instead of the original folder, 415 00:15:54,360 --> 00:15:55,800 you point it to a "Temp" folder, 416 00:15:55,800 --> 00:15:57,850 or I don't know, some folder you control. 417 00:15:58,800 --> 00:16:00,210 You're gonna start the application 418 00:16:00,210 --> 00:16:02,490 and using, for example, "ProcMon", 419 00:16:02,490 --> 00:16:03,662 you just check, right? 420 00:16:03,662 --> 00:16:08,340 It's this application, now, checking the folder I specified. 421 00:16:08,340 --> 00:16:10,650 Because I updated the environment variable 422 00:16:10,650 --> 00:16:12,780 and then, well, hopefully, profit. 423 00:16:12,780 --> 00:16:15,360 So, if you look at the diagram over there, at the top, 424 00:16:15,360 --> 00:16:17,730 a normal run of this trusted program, 425 00:16:17,730 --> 00:16:20,100 it might try to load a DLL 426 00:16:20,100 --> 00:16:23,400 from a location, using this variable called "SOMEVARIABLE". 427 00:16:23,400 --> 00:16:27,240 And normally, that would resolve to "C\Legitimate\Path" 428 00:16:27,240 --> 00:16:29,223 and then, the name of the DLL. 429 00:16:29,223 --> 00:16:30,056 (smacks lips) 430 00:16:30,056 --> 00:16:32,460 What I'm proposing, is manipulating that, right? 431 00:16:32,460 --> 00:16:33,750 On process-level, 432 00:16:33,750 --> 00:16:38,550 we change the environment variable to, say, "C\Evil\Path" 433 00:16:38,550 --> 00:16:40,800 and then, hopefully, if it runs, 434 00:16:40,800 --> 00:16:43,890 it will, now, load the DLL from my location instead. 435 00:16:43,890 --> 00:16:45,810 And if the application is stupid enough, 436 00:16:45,810 --> 00:16:47,580 not to check if there's a signature, 437 00:16:47,580 --> 00:16:50,610 or do some other form of verification, 438 00:16:50,610 --> 00:16:52,470 it might, now, load my DLL 439 00:16:52,470 --> 00:16:54,903 and that would mean a new type of DLL hijacking. 440 00:16:56,880 --> 00:16:58,530 So, this is a working example. 441 00:16:58,530 --> 00:17:02,010 This is an example that I found in the "System32" folder, 442 00:17:02,010 --> 00:17:05,420 you got an executable that is called "hostname". 443 00:17:06,288 --> 00:17:07,710 It's a very simple one, it's very boring, 444 00:17:07,710 --> 00:17:08,990 it just prints the host name, right? 445 00:17:08,990 --> 00:17:11,340 It just prints the name of your computer. 446 00:17:11,340 --> 00:17:12,900 But it turns out that if you run it, 447 00:17:12,900 --> 00:17:16,230 just without any command line arguments, just "hostname", 448 00:17:16,230 --> 00:17:18,540 it will load, I think, it's three DLLs, 449 00:17:18,540 --> 00:17:20,340 one of which is the one you see here. 450 00:17:20,340 --> 00:17:23,340 So, it tries to load a DLL dynamically 451 00:17:23,340 --> 00:17:25,770 from the "SystemRoot" folder 452 00:17:25,770 --> 00:17:30,770 and then, "System32" slash, what is it, "mswsock.dll". 453 00:17:31,260 --> 00:17:33,810 So, normally, that means, it will load it 454 00:17:33,810 --> 00:17:38,573 from "C\Windows\System32\mswsock.dll". 455 00:17:40,110 --> 00:17:42,390 However, if I, now, change the environment variable 456 00:17:42,390 --> 00:17:43,710 with the "PowerShell" that you see there 457 00:17:43,710 --> 00:17:45,000 at the bottom of the screen, 458 00:17:45,000 --> 00:17:50,000 I can, now, alter the path and trick it into loading my DLL. 459 00:17:50,160 --> 00:17:52,320 So, it's a number of ways in which you can do this. 460 00:17:52,320 --> 00:17:55,320 This is a way of doing it in "PowerShell". 461 00:17:55,320 --> 00:17:57,210 So, it uses "CLR". 462 00:17:57,210 --> 00:17:59,040 So, very simply put, 463 00:17:59,040 --> 00:18:00,540 you define any object, 464 00:18:00,540 --> 00:18:03,750 you point to the original binary, right? 465 00:18:03,750 --> 00:18:04,920 We don't need to move "hostname", 466 00:18:04,920 --> 00:18:06,720 we don't need to do anything special, 467 00:18:06,720 --> 00:18:10,500 we just say, "This is the executable I want to run." 468 00:18:10,500 --> 00:18:13,590 I, then, remove the SystemRoot's variable. 469 00:18:13,590 --> 00:18:16,463 I, then, add it again with a new path. 470 00:18:16,463 --> 00:18:20,040 So, the new path is now "C\Temp\Evil" 471 00:18:20,040 --> 00:18:20,940 and then, the remaining code, 472 00:18:20,940 --> 00:18:22,860 is just getting the new object ready 473 00:18:22,860 --> 00:18:24,663 and starting the new process. 474 00:18:26,788 --> 00:18:27,621 (smacks lips) 475 00:18:27,621 --> 00:18:28,454 Right. 476 00:18:28,454 --> 00:18:29,287 Demo time. 477 00:18:29,287 --> 00:18:31,320 So, first of all, here, I'm showing 478 00:18:31,320 --> 00:18:35,610 that I have this "Temp" folder slash "Evil" 479 00:18:35,610 --> 00:18:37,290 and that I got this DLL defined. 480 00:18:37,290 --> 00:18:39,930 So, I created this sub-folder called "System32" 481 00:18:39,930 --> 00:18:41,103 with the DLL in there. 482 00:18:42,120 --> 00:18:44,310 Now, pasting the code, I just described. 483 00:18:44,310 --> 00:18:46,530 Hopefully, when I run it, 484 00:18:46,530 --> 00:18:49,260 it should give some sort of visual feedback, 485 00:18:49,260 --> 00:18:51,600 but also, at the top, you see "ProcMon" running. 486 00:18:51,600 --> 00:18:54,090 So, hopefully, that will, also, demonstrate 487 00:18:54,090 --> 00:18:57,270 that it loaded the DLL from my location, right? 488 00:18:57,270 --> 00:19:00,600 So, not from "System32", but from my location. 489 00:19:00,600 --> 00:19:02,430 Well, you might not be able to see it, 490 00:19:02,430 --> 00:19:05,340 but it popped a window that said, "Hello, DEFCON". 491 00:19:05,340 --> 00:19:06,600 And of course, it popped calc, 492 00:19:06,600 --> 00:19:08,610 because otherwise, you wouldn't know I did something bad. 493 00:19:08,610 --> 00:19:09,813 So, there is calc. 494 00:19:11,226 --> 00:19:12,059 (laughs) 495 00:19:12,059 --> 00:19:15,270 (audience applauds) 496 00:19:15,270 --> 00:19:16,980 And in the "ProcMon" window, 497 00:19:16,980 --> 00:19:17,813 you can, now, see, 498 00:19:17,813 --> 00:19:18,750 again, it might be a bit too small, 499 00:19:18,750 --> 00:19:20,160 but it's, basically, confirming 500 00:19:20,160 --> 00:19:22,590 that the executable is in the expected location, 501 00:19:22,590 --> 00:19:25,137 but it loaded my DLL from my "Temp" location, 502 00:19:25,137 --> 00:19:26,613 the folder we just looked at. 503 00:19:27,860 --> 00:19:28,693 (smacks lips) 504 00:19:28,693 --> 00:19:29,903 So, bit of a recap, right? 505 00:19:29,903 --> 00:19:31,170 'Cause, okay, fine, 506 00:19:31,170 --> 00:19:33,780 I pop calc, big deal. 507 00:19:33,780 --> 00:19:35,370 Why should we care? 508 00:19:35,370 --> 00:19:36,540 So, the great thing is, 509 00:19:36,540 --> 00:19:38,910 is that from an offensive point of view, 510 00:19:38,910 --> 00:19:40,980 you, only, need to bring the DLL, right? 511 00:19:40,980 --> 00:19:43,680 Because "hostname" is, already, on the machine. 512 00:19:43,680 --> 00:19:46,620 You just start a new process, you update a variable 513 00:19:46,620 --> 00:19:48,360 and that means that you don't need 514 00:19:48,360 --> 00:19:49,980 to bring in your own executable, 515 00:19:49,980 --> 00:19:53,491 which is, typically, the case for DLL side-loading. 516 00:19:53,491 --> 00:19:54,324 (smacks lips) 517 00:19:54,324 --> 00:19:56,100 There's, also, no special command lines involved 518 00:19:56,100 --> 00:19:56,933 and you don't need to, 519 00:19:56,933 --> 00:19:58,050 I don't know, suspend the process 520 00:19:58,050 --> 00:19:59,340 when you started this, 521 00:19:59,340 --> 00:20:00,173 as you've seen, right? 522 00:20:00,173 --> 00:20:02,040 It's just a couple of lines in "PowerShell", 523 00:20:02,040 --> 00:20:03,418 it's pretty straightforward. 524 00:20:03,418 --> 00:20:04,251 (smacks lips) 525 00:20:04,251 --> 00:20:06,480 And one thing, I really want to emphasize, right? 526 00:20:06,480 --> 00:20:09,540 Environment variables are defined in the registry, 527 00:20:09,540 --> 00:20:11,603 but what we just did, we didn't change the registry, right? 528 00:20:11,603 --> 00:20:13,170 We just started the process 529 00:20:13,170 --> 00:20:15,590 and told it to overwrite the environment variables, 530 00:20:15,590 --> 00:20:16,950 it was aware of. 531 00:20:16,950 --> 00:20:19,950 So, that means there is no registry footprint, 532 00:20:19,950 --> 00:20:21,000 if anything, right? 533 00:20:21,000 --> 00:20:23,220 If I were to change the environment variable, 534 00:20:23,220 --> 00:20:25,830 like, if I change "SystemRoot" in the registry, 535 00:20:25,830 --> 00:20:27,167 it would break my entire system, right? 536 00:20:27,167 --> 00:20:29,360 'Cause so many programs use it. 537 00:20:29,360 --> 00:20:30,380 It would not find DLLs, 538 00:20:30,380 --> 00:20:32,610 it would just, like, make your computer unbootable. 539 00:20:32,610 --> 00:20:33,900 So, we don't want that. 540 00:20:33,900 --> 00:20:35,490 We changed it on process-level 541 00:20:35,490 --> 00:20:37,203 and well, we've shown, it worked. 542 00:20:38,610 --> 00:20:41,010 Also, from an "AV" and "EDR" perspective, 543 00:20:41,010 --> 00:20:43,380 they can see environment variables on process-level, 544 00:20:43,380 --> 00:20:46,230 but very rarely, in my experience, 545 00:20:46,230 --> 00:20:47,880 they do, actually, hunt for it, right, 546 00:20:47,880 --> 00:20:50,163 or you're able to write rules for it. 547 00:20:51,471 --> 00:20:52,304 (smacks lips) 548 00:20:52,304 --> 00:20:53,137 So, that means that you might get away with it, 549 00:20:53,137 --> 00:20:55,380 because the, really, obvious things, 550 00:20:55,380 --> 00:20:58,180 like, command line and registry artifacts are not there. 551 00:20:59,040 --> 00:21:02,040 And yeah, as I said, this was an example with "PowerShell", 552 00:21:02,040 --> 00:21:03,270 but, actually, you can, also, do it 553 00:21:03,270 --> 00:21:04,830 with VBScript or JScripts. 554 00:21:04,830 --> 00:21:06,480 You could, literally, write a macro 555 00:21:06,480 --> 00:21:08,880 that does this in a very stealthy way. 556 00:21:08,880 --> 00:21:12,000 And because you use legitimate processes, 557 00:21:12,000 --> 00:21:13,890 like, with some DLL hijacking, 558 00:21:13,890 --> 00:21:15,840 you would have to run a process from a "Temp" folder, 559 00:21:15,840 --> 00:21:18,723 but you just run a process from "System32", right? 560 00:21:19,590 --> 00:21:21,203 Again, you might get away with that. 561 00:21:22,140 --> 00:21:23,190 You could, of course, also, run it 562 00:21:23,190 --> 00:21:24,570 from an executable itself. 563 00:21:24,570 --> 00:21:26,460 You could write a "C" or some "C" code 564 00:21:26,460 --> 00:21:28,890 to launch a process with a different environment variable, 565 00:21:28,890 --> 00:21:30,840 but that, sort of, defeats the whole point. 566 00:21:30,840 --> 00:21:34,140 So, having these script languages support this, 567 00:21:34,140 --> 00:21:35,433 makes it really powerful. 568 00:21:36,305 --> 00:21:37,138 (smacks lips) 569 00:21:37,138 --> 00:21:38,640 So, this is just a static screenshot 570 00:21:38,640 --> 00:21:41,250 of how you might do it in "VBScript". 571 00:21:41,250 --> 00:21:42,180 You see the "Command Prompt", 572 00:21:42,180 --> 00:21:45,870 which is just executing the "VBScript" file. 573 00:21:45,870 --> 00:21:47,853 On the right-head side, you see the code in "VBScript", 574 00:21:47,853 --> 00:21:49,470 it's only four lines. 575 00:21:49,470 --> 00:21:50,880 You could, actually, do it in three, 576 00:21:50,880 --> 00:21:53,550 if you group some stuff together. 577 00:21:53,550 --> 00:21:56,430 And then, at the bottom, you see how it worked. 578 00:21:56,430 --> 00:21:58,260 So, if you look at the "VBScript" code, 579 00:21:58,260 --> 00:22:01,890 it just asks for the process-level variables, 580 00:22:01,890 --> 00:22:02,723 it updates it, 581 00:22:02,723 --> 00:22:05,580 "SystemRoot", again, change it to a "Temp" folder 582 00:22:05,580 --> 00:22:09,420 and then, in this case, it runs another executable, "SLUI" 583 00:22:09,420 --> 00:22:11,040 and then, at the bottom, you see the evidence 584 00:22:11,040 --> 00:22:13,800 that it loaded not one, but, actually, three DLLs 585 00:22:13,800 --> 00:22:14,633 from my folder. 586 00:22:15,690 --> 00:22:16,560 You might, also, see 587 00:22:16,560 --> 00:22:21,030 that CScripts, also, loaded two DLLs from my folder. 588 00:22:21,030 --> 00:22:22,920 So, that's something to be aware of. 589 00:22:22,920 --> 00:22:24,270 Some scripting languages, 590 00:22:24,270 --> 00:22:27,630 if you change the environment variable on process-level, 591 00:22:27,630 --> 00:22:30,480 it will start using it itself, too. 592 00:22:30,480 --> 00:22:32,400 So, if "CScript" needs a DLL 593 00:22:32,400 --> 00:22:34,200 and it relies on the same variable, 594 00:22:34,200 --> 00:22:36,660 it might, actually, break. 595 00:22:36,660 --> 00:22:38,250 There's a way of working around this, by the way. 596 00:22:38,250 --> 00:22:40,080 But I thought, I do wanna point it out 597 00:22:40,080 --> 00:22:41,610 that it doesn't come without challenge, 598 00:22:41,610 --> 00:22:45,750 but it's funny how different the language is implemented 599 00:22:45,750 --> 00:22:46,700 in a different way. 600 00:22:48,480 --> 00:22:51,660 Cool, so, final recap for the technique itself. 601 00:22:51,660 --> 00:22:53,340 So, already, alluded 602 00:22:53,340 --> 00:22:55,290 to most of these DDL side-loading, right? 603 00:22:55,290 --> 00:22:56,490 Need to bring an executable, 604 00:22:56,490 --> 00:22:57,870 we don't need that. 605 00:22:57,870 --> 00:22:59,640 DLL search order hijacking. 606 00:22:59,640 --> 00:23:02,550 Again, I think, fewer candidates than most people realize. 607 00:23:02,550 --> 00:23:04,080 There's, only, a few really obvious ones. 608 00:23:04,080 --> 00:23:06,030 So, that means detection is easier. 609 00:23:06,030 --> 00:23:07,890 In this case, I will show shortly, 610 00:23:07,890 --> 00:23:10,650 there are many candidates you can choose from. 611 00:23:10,650 --> 00:23:12,210 And same with DLL substitution, 612 00:23:12,210 --> 00:23:13,860 or input-based DLL hijacking, right? 613 00:23:13,860 --> 00:23:16,530 It comes all with extra steps 614 00:23:16,530 --> 00:23:19,470 that just mean that you are more likely to be picked up. 615 00:23:19,470 --> 00:23:20,970 We don't have any of that. 616 00:23:20,970 --> 00:23:23,370 And there are a couple of downsides, 617 00:23:23,370 --> 00:23:25,080 but I think, the main footprint 618 00:23:25,080 --> 00:23:26,310 that you have with this technique, 619 00:23:26,310 --> 00:23:28,260 is the planting of the DLL, right? 620 00:23:28,260 --> 00:23:30,870 At some point, you need to put that DLL in that folder, 621 00:23:30,870 --> 00:23:32,400 that it's gonna load it from. 622 00:23:32,400 --> 00:23:33,720 But if you think about it, 623 00:23:33,720 --> 00:23:34,590 you're always gonna have that 624 00:23:34,590 --> 00:23:35,940 with DLL (indistinct) hijacking, right? 625 00:23:35,940 --> 00:23:38,100 You need to execute a DLL, 626 00:23:38,100 --> 00:23:39,540 it needs to live somewhere on disc. 627 00:23:39,540 --> 00:23:41,400 So, again, if you compare it 628 00:23:41,400 --> 00:23:42,960 to the other DLL hijacking ones, 629 00:23:42,960 --> 00:23:44,760 this one is rather stealthy. 630 00:23:44,760 --> 00:23:45,900 Doesn't mean it's undetectable, 631 00:23:45,900 --> 00:23:48,513 but it's doing a better job, I think. 632 00:23:50,079 --> 00:23:51,030 (smacks lips) 633 00:23:51,030 --> 00:23:53,250 Cool, so, so far, I've only talked to you 634 00:23:53,250 --> 00:23:54,840 about one or two executables, 635 00:23:54,840 --> 00:23:56,070 which were a bit anecdotal, right, 636 00:23:56,070 --> 00:23:58,563 like, how do you find which ones are vulnerable? 637 00:23:59,730 --> 00:24:01,920 So, again, we get into the hacker's mindset. 638 00:24:01,920 --> 00:24:04,560 How would you turn this single observation 639 00:24:04,560 --> 00:24:07,110 into a systemic approach? 640 00:24:07,110 --> 00:24:08,910 So, here's an idea, right? 641 00:24:08,910 --> 00:24:10,050 I defined a scope 642 00:24:10,050 --> 00:24:12,960 for the executables and DLLs, I want to test. 643 00:24:12,960 --> 00:24:14,190 So, in this case, 644 00:24:14,190 --> 00:24:16,290 I just looked at all the DLLs 645 00:24:16,290 --> 00:24:18,949 that live in the "System32" folder. 646 00:24:18,949 --> 00:24:19,782 (smacks lips) 647 00:24:19,782 --> 00:24:20,615 What I did, 648 00:24:20,615 --> 00:24:23,310 is create implants for each and every one of them. 649 00:24:23,310 --> 00:24:24,960 How I did that, I'll show shortly. 650 00:24:24,960 --> 00:24:28,920 But, basically, every DLL gets its own clone. 651 00:24:28,920 --> 00:24:30,180 And whenever it's loaded, 652 00:24:30,180 --> 00:24:33,180 it would write a fingerprint file to disk. 653 00:24:33,180 --> 00:24:36,090 So, a fingerprint file is literally just an empty text file, 654 00:24:36,090 --> 00:24:40,530 but the file name shows you which DLL was loaded 655 00:24:40,530 --> 00:24:42,900 and which process it was loaded by. 656 00:24:42,900 --> 00:24:44,880 So, I will offer with an example of that in a bit, 657 00:24:44,880 --> 00:24:46,080 but basically, it means 658 00:24:46,080 --> 00:24:48,780 that if my DLL was loaded successfully, 659 00:24:48,780 --> 00:24:51,360 I'll have evidence in the form of a fingerprint file, 660 00:24:51,360 --> 00:24:53,430 which like, a hundred percent guarantees 661 00:24:53,430 --> 00:24:56,417 that my code was loaded and executed. 662 00:24:56,417 --> 00:24:57,250 (smacks lips) 663 00:24:57,250 --> 00:24:58,083 So, that's the prep. 664 00:24:58,083 --> 00:24:59,160 Then, we go to the execution. 665 00:24:59,160 --> 00:25:02,418 So, now, I have thousands of DLLs, 666 00:25:02,418 --> 00:25:03,480 'cause in "System32", 667 00:25:03,480 --> 00:25:04,597 there is a lot of DLLs 668 00:25:05,921 --> 00:25:07,740 (smacks lips) I, now, need to define the scope 669 00:25:07,740 --> 00:25:09,750 for the applications I need to test. 670 00:25:09,750 --> 00:25:12,000 So, say, again, we use "System32", right? 671 00:25:12,000 --> 00:25:15,453 We just do a star search for all the executables in there. 672 00:25:16,306 --> 00:25:17,520 What I, now, would do, 673 00:25:17,520 --> 00:25:20,670 is run each and every executable, 674 00:25:20,670 --> 00:25:21,990 just one by one, 675 00:25:21,990 --> 00:25:23,730 but with the updated environment variable, 676 00:25:23,730 --> 00:25:25,200 very similar to the "PowerShell" script, 677 00:25:25,200 --> 00:25:26,390 I just showed you, right? 678 00:25:26,390 --> 00:25:27,780 In that case, I just ran one, 679 00:25:27,780 --> 00:25:29,490 where you just turned it into a full loop, 680 00:25:29,490 --> 00:25:31,350 iterate over the executables, 681 00:25:31,350 --> 00:25:32,460 pointing it to the folder 682 00:25:32,460 --> 00:25:35,130 with all these thousands of implants. 683 00:25:35,130 --> 00:25:37,470 And then, hopefully if they worked successfully, 684 00:25:37,470 --> 00:25:39,180 we can, now, just validate it 685 00:25:39,180 --> 00:25:40,830 by looking at the fingerprint files. 686 00:25:40,830 --> 00:25:44,190 These will tell me what executables worked 687 00:25:44,190 --> 00:25:45,297 and which DLLs were loaded 688 00:25:45,297 --> 00:25:49,083 and that means, that we can use them in proper attacks. 689 00:25:50,009 --> 00:25:52,620 (smacks lips) 690 00:25:52,620 --> 00:25:54,780 Right, so, some of you, 691 00:25:54,780 --> 00:25:56,867 may have, actually, done DLL hijacking before, right? 692 00:25:56,867 --> 00:26:01,560 'Cause it's very similar across these different variants. 693 00:26:01,560 --> 00:26:03,510 There are a couple of challenges there. 694 00:26:03,510 --> 00:26:06,390 So, stability being the main one. 695 00:26:06,390 --> 00:26:10,200 If you just generate a dummy DLL 696 00:26:10,200 --> 00:26:12,360 that just has a DLL main and nothing else, 697 00:26:12,360 --> 00:26:14,310 it, typically, does not get loaded 698 00:26:14,310 --> 00:26:16,860 by the vulnerable application. 699 00:26:16,860 --> 00:26:20,502 Typically, applications rely on the exports, 700 00:26:20,502 --> 00:26:23,910 the export table that tells you 701 00:26:23,910 --> 00:26:25,830 which functions you can call. 702 00:26:25,830 --> 00:26:28,200 So, if those are not present, 703 00:26:28,200 --> 00:26:30,600 the executable might reject the file. 704 00:26:30,600 --> 00:26:32,280 It might, actually, become unstable, 705 00:26:32,280 --> 00:26:33,510 or give some visual feedback 706 00:26:33,510 --> 00:26:35,040 and again, that means, you can't really use it 707 00:26:35,040 --> 00:26:36,420 for an attack. 708 00:26:36,420 --> 00:26:38,790 So, a great way to overcome that, 709 00:26:38,790 --> 00:26:42,480 is to use "DLL Proxying" or "Function Redirection". 710 00:26:42,480 --> 00:26:44,400 So, the great thing about "PE" files, 711 00:26:44,400 --> 00:26:46,440 is that you can define exports. 712 00:26:46,440 --> 00:26:50,100 So, again, these are public-facing, yeah, functions, 713 00:26:50,100 --> 00:26:51,153 you can call. 714 00:26:52,141 --> 00:26:52,974 But the great thing is, 715 00:26:52,974 --> 00:26:55,650 you can, actually, point these functions or these exports 716 00:26:55,650 --> 00:26:58,066 to external files. 717 00:26:58,066 --> 00:26:58,899 (smacks lips) 718 00:26:58,899 --> 00:26:59,732 So, through that, 719 00:26:59,732 --> 00:27:01,860 I can, actually, in my implant, 720 00:27:01,860 --> 00:27:03,810 leverage the legitimate functionality. 721 00:27:03,810 --> 00:27:05,730 So, the DLL would, literally, do the same thing 722 00:27:05,730 --> 00:27:07,260 as the genuine one, 723 00:27:07,260 --> 00:27:09,990 but, still, include my malicious code. 724 00:27:09,990 --> 00:27:12,270 So, let me actually, quickly, show that 725 00:27:12,270 --> 00:27:14,970 how this works in the context of this attack. 726 00:27:14,970 --> 00:27:18,150 So, here, we have our legitimate application, again 727 00:27:18,150 --> 00:27:21,510 and imagine, it is trying to load "SomeDll.dll", right? 728 00:27:21,510 --> 00:27:23,583 So, it's the implant I created. 729 00:27:24,420 --> 00:27:26,823 And in this case, it is a clone of a DLL 730 00:27:26,823 --> 00:27:28,418 that has two exports, 731 00:27:28,418 --> 00:27:30,420 "ExportA" and "ExportB". 732 00:27:30,420 --> 00:27:32,580 If I were, now, to generate an implant, right, 733 00:27:32,580 --> 00:27:35,250 I don't wanna reverse-engineer this DLL, right? 734 00:27:35,250 --> 00:27:37,231 That's gonna cost way too much time. 735 00:27:37,231 --> 00:27:38,064 And I, already, said, right, 736 00:27:38,064 --> 00:27:40,590 there's thousands of DLLs that does not scale. 737 00:27:40,590 --> 00:27:42,690 So, instead, what I do? 738 00:27:42,690 --> 00:27:44,077 In my implant, I just say, 739 00:27:44,077 --> 00:27:47,190 "Well, I have an 'ExportA' and I have an 'ExportB', 740 00:27:47,190 --> 00:27:48,900 but the functionality lives elsewhere. 741 00:27:48,900 --> 00:27:50,100 It's over here." 742 00:27:50,100 --> 00:27:53,250 And then, you just point it to the legitimate location. 743 00:27:53,250 --> 00:27:55,560 So, here, you see, at the bottom, right, 744 00:27:55,560 --> 00:27:57,510 you see my fake path, again. 745 00:27:57,510 --> 00:27:59,400 And I say, "Well, if you call 'ExportA', 746 00:27:59,400 --> 00:28:02,640 please go to 'C\Windows\SomeDll". 747 00:28:02,640 --> 00:28:03,627 That's where you find it. 748 00:28:03,627 --> 00:28:07,050 And that means that the executable here, 749 00:28:07,050 --> 00:28:09,900 whenever it calls my DLL, it would load my code. 750 00:28:09,900 --> 00:28:11,280 But whenever it calls a function, 751 00:28:11,280 --> 00:28:13,440 it would go to that legitimate DLL. 752 00:28:13,440 --> 00:28:14,273 So, that is great, 753 00:28:14,273 --> 00:28:17,670 because that means that the program is less-likely to break. 754 00:28:17,670 --> 00:28:20,010 So, it's more likely to accept my DLL 755 00:28:20,010 --> 00:28:20,843 and therefore, 756 00:28:20,843 --> 00:28:23,613 I can, actually, more reliably, perform DLL hijacking. 757 00:28:25,140 --> 00:28:26,550 So, it was one issue, the reliability. 758 00:28:26,550 --> 00:28:27,780 So, with "DLL Proxying", 759 00:28:27,780 --> 00:28:30,360 you, already, cover most of that. 760 00:28:30,360 --> 00:28:33,150 But then, some executables, also, leverage DLLs 761 00:28:33,150 --> 00:28:36,480 to get like, image files, or cursor files, 762 00:28:36,480 --> 00:28:38,220 or like, any sort of resources. 763 00:28:38,220 --> 00:28:41,040 You can embed these in "PE" files. 764 00:28:41,040 --> 00:28:42,810 So, another issue is that 765 00:28:42,810 --> 00:28:44,910 if you don't have these in your implant, 766 00:28:44,910 --> 00:28:47,159 that the executable might break. 767 00:28:47,159 --> 00:28:47,992 (smacks lips) 768 00:28:47,992 --> 00:28:51,390 So, again, to maximize the number of targets I could find, 769 00:28:51,390 --> 00:28:53,460 I, also, implemented research cloning, 770 00:28:53,460 --> 00:28:56,280 meaning, it, literally, just copies the resource section 771 00:28:56,280 --> 00:28:57,600 to the next DLL. 772 00:28:57,600 --> 00:28:59,430 And again, that, further, increases the number 773 00:28:59,430 --> 00:29:01,773 of executables that you can choose from. 774 00:29:03,386 --> 00:29:04,710 (smacks lips) 775 00:29:04,710 --> 00:29:05,970 Great, so, this is what it looks like. 776 00:29:05,970 --> 00:29:07,800 So, this is a bash script, 777 00:29:07,800 --> 00:29:09,420 I'll be releasing it later, today. 778 00:29:09,420 --> 00:29:11,580 It uses all sorts of open-source tools, 779 00:29:11,580 --> 00:29:15,106 but, basically, it just looks at the legitimate DLL, 780 00:29:15,106 --> 00:29:15,939 (smacks lips) 781 00:29:15,939 --> 00:29:16,860 it looks at the export table, 782 00:29:16,860 --> 00:29:17,810 it, then, copies it, 783 00:29:17,810 --> 00:29:20,700 it creates these redirection rules, 784 00:29:20,700 --> 00:29:22,920 it, then, copies the resource section, as well. 785 00:29:22,920 --> 00:29:23,753 And then, by the end, 786 00:29:23,753 --> 00:29:26,940 you have an implant DLL with your malicious code, 787 00:29:26,940 --> 00:29:30,570 with these function redirections as well as the resources 788 00:29:30,570 --> 00:29:31,670 that have been cloned. 789 00:29:32,790 --> 00:29:34,260 So, in my test, here, 790 00:29:34,260 --> 00:29:37,590 with the scope and everything we were just talking about, 791 00:29:37,590 --> 00:29:40,320 this is, literally, the main .dll file. 792 00:29:40,320 --> 00:29:42,690 As you see, it's nothing fancy. 793 00:29:42,690 --> 00:29:43,523 It, basically, says, 794 00:29:43,523 --> 00:29:44,440 "Whenever I'm called 795 00:29:45,450 --> 00:29:49,050 and it's a process-attached or a threat-attached action, 796 00:29:49,050 --> 00:29:51,363 then, just call "generate_fingerprint" 797 00:29:52,380 --> 00:29:55,200 with the name of the executable to run it. 798 00:29:55,200 --> 00:29:56,220 And as I, already, said, 799 00:29:56,220 --> 00:29:58,440 that function is, literally, just creating a text file, 800 00:29:58,440 --> 00:30:00,870 saying, "First, the name of the DLL, 801 00:30:00,870 --> 00:30:02,490 then, the name of the executable 802 00:30:02,490 --> 00:30:04,080 and then, if the file is there, 803 00:30:04,080 --> 00:30:06,897 then, hopefully, it's proof that it worked." 804 00:30:08,219 --> 00:30:09,390 (smacks lips) 805 00:30:09,390 --> 00:30:11,070 This is, then, how you would run it, right? 806 00:30:11,070 --> 00:30:13,680 So, I have, now, thousands of DLL files. 807 00:30:13,680 --> 00:30:15,570 This is the "PowerShell" script, I was talking about. 808 00:30:15,570 --> 00:30:18,600 It's a modified version of the one we looked at in the demo. 809 00:30:18,600 --> 00:30:20,040 As I said, it's just a full loop, right? 810 00:30:20,040 --> 00:30:24,090 It just iterates over everything in the "System32" folder, 811 00:30:24,090 --> 00:30:26,460 it, then, changes the environment variable, 812 00:30:26,460 --> 00:30:29,490 pointing it to the folder with all the DLL implants 813 00:30:29,490 --> 00:30:31,770 and then, just runs them one by one. 814 00:30:31,770 --> 00:30:33,930 And then, hopefully, if you run that, 815 00:30:33,930 --> 00:30:37,110 you get lots of these fingerprint files, right? 816 00:30:37,110 --> 00:30:39,873 So, when I run it on the latest version of "Windows 11", 817 00:30:39,873 --> 00:30:41,610 that I could get hold of, 818 00:30:41,610 --> 00:30:42,443 this is what happened. 819 00:30:42,443 --> 00:30:43,710 So, this is a folder, 820 00:30:43,710 --> 00:30:45,150 it's, probably, too small for the back. 821 00:30:45,150 --> 00:30:46,917 But again, you see, for example, 822 00:30:46,917 --> 00:30:50,220 (indistinct) loading a DLL from the "System32" folder 823 00:30:50,220 --> 00:30:52,020 and the fact that the file is here, right? 824 00:30:52,020 --> 00:30:53,040 It's just an empty text file. 825 00:30:53,040 --> 00:30:55,110 But that means that my code was loaded, 826 00:30:55,110 --> 00:30:56,760 it was successful. 827 00:30:56,760 --> 00:30:58,740 As you may be able to see from the scroll bar, 828 00:30:58,740 --> 00:31:01,590 there are quite a few text files in there. 829 00:31:01,590 --> 00:31:04,050 So, that means, there's quite a few options you have 830 00:31:04,050 --> 00:31:05,902 to get this to work. 831 00:31:05,902 --> 00:31:06,735 (smacks lips) 832 00:31:06,735 --> 00:31:09,240 So, what I'm releasing today, is the code that I used, 833 00:31:09,240 --> 00:31:11,220 so, you can use this for your own research. 834 00:31:11,220 --> 00:31:13,590 I've only focused on the "System32" folder, 835 00:31:13,590 --> 00:31:16,200 but if you wanna leverage any of this yourself, 836 00:31:16,200 --> 00:31:18,270 which includes the "Function Redirection" 837 00:31:18,270 --> 00:31:19,410 and the "Resource Cloning", 838 00:31:19,410 --> 00:31:22,830 you can find it on my "GitHub" page that's live now. 839 00:31:22,830 --> 00:31:23,790 I've used it in "Linux", 840 00:31:23,790 --> 00:31:25,347 but it uses "MinGW", 841 00:31:25,347 --> 00:31:27,930 so, you should be able to use it on "Windows", as well. 842 00:31:27,930 --> 00:31:31,500 And yeah, I mean, let's, now, take a look 843 00:31:31,500 --> 00:31:32,760 at some of the results, right? 844 00:31:32,760 --> 00:31:34,410 So, you saw these fingerprint files, 845 00:31:34,410 --> 00:31:36,564 but what does that really mean? 846 00:31:36,564 --> 00:31:37,397 (smacks lips) 847 00:31:37,397 --> 00:31:38,230 So, in the scope 848 00:31:38,230 --> 00:31:42,300 that I tested it on, "System32" folder, "Windows 11", 849 00:31:42,300 --> 00:31:47,300 I found 82 unique executables to load 91 unique DLLs. 850 00:31:48,540 --> 00:31:51,480 But because most executables load multiple DLLs, 851 00:31:51,480 --> 00:31:53,010 there's, actually, nearly 400, 852 00:31:53,010 --> 00:31:56,370 or 398 unique combinations there. 853 00:31:56,370 --> 00:31:58,740 So, that's quite a few options there, right? 854 00:31:58,740 --> 00:32:01,890 So, to my earlier point with DLL search order hijacking, 855 00:32:01,890 --> 00:32:03,750 you can, usually, only choose from a couple, 856 00:32:03,750 --> 00:32:07,901 but here, you got 400 out of the box on "Windows 11". 857 00:32:07,901 --> 00:32:09,660 (smacks lips) 858 00:32:09,660 --> 00:32:12,870 Then, I did some spot-checking on other tools. 859 00:32:12,870 --> 00:32:15,720 So, some other very common enterprise tools like "Office", 860 00:32:15,720 --> 00:32:17,970 so, I tested "Word", "PowerPoint", "Excel". 861 00:32:17,970 --> 00:32:20,190 Again, all of these are vulnerable 862 00:32:20,190 --> 00:32:21,900 to this type of DLL hijacking. 863 00:32:21,900 --> 00:32:23,130 They load at least one, 864 00:32:23,130 --> 00:32:26,280 but, usually, like, five or six DLLs. 865 00:32:26,280 --> 00:32:28,560 And if you change the "SystemRoot" variable, 866 00:32:28,560 --> 00:32:32,345 you can trick it into loading your malicious DLL. 867 00:32:32,345 --> 00:32:33,178 (smacks lips) 868 00:32:33,178 --> 00:32:34,011 Same with some web browsers, 869 00:32:34,011 --> 00:32:35,940 I tried "Edge", "Chrome", "Firefox". 870 00:32:35,940 --> 00:32:39,510 I tested communication software like "Teams" and "Zoom". 871 00:32:39,510 --> 00:32:41,820 All of these are vulnerable. 872 00:32:41,820 --> 00:32:43,890 And to me, that shows, right? 873 00:32:43,890 --> 00:32:46,140 So, the number of 400 is great 874 00:32:46,140 --> 00:32:47,340 and it sounds really cool. 875 00:32:47,340 --> 00:32:48,780 But the overarching point, 876 00:32:48,780 --> 00:32:51,240 is that it's not about these individual tools, 877 00:32:51,240 --> 00:32:53,040 it's a wider problem, right? 878 00:32:53,040 --> 00:32:56,250 Applications rely on their "SystemRoot" variable 879 00:32:56,250 --> 00:32:58,980 and some others and they don't properly test 880 00:32:58,980 --> 00:33:01,860 and that means, that there are just many, many results. 881 00:33:01,860 --> 00:33:04,680 So, this is a whole new class of DLL hijacking 882 00:33:04,680 --> 00:33:06,030 that we can, now, leverage. 883 00:33:07,955 --> 00:33:08,788 (smacks lips) 884 00:33:08,788 --> 00:33:12,450 Cool, then, before I go to the next section, 885 00:33:12,450 --> 00:33:16,260 some quick remarks on like, how can we take this further? 886 00:33:16,260 --> 00:33:18,660 So, so far, we've only looked at execution, right, 887 00:33:18,660 --> 00:33:21,780 which is what you, normally, do anyway with DLL hijacking. 888 00:33:21,780 --> 00:33:22,613 But is there a way 889 00:33:22,613 --> 00:33:25,925 in which we can use this more persistently, for example? 890 00:33:25,925 --> 00:33:26,758 (smacks lips) 891 00:33:26,758 --> 00:33:28,230 Well, that is a bit of a challenge, 892 00:33:28,230 --> 00:33:30,150 because we need to start the process 893 00:33:30,150 --> 00:33:32,397 with the updated environment variables, right? 894 00:33:32,397 --> 00:33:33,690 And we already said, 895 00:33:33,690 --> 00:33:35,782 we don't wanna change the "CURRENT_USER", 896 00:33:35,782 --> 00:33:36,870 or "LOCAL_MACHINE" one, 897 00:33:36,870 --> 00:33:38,460 because that would break everything. 898 00:33:38,460 --> 00:33:40,770 So, how do you start a process, in a way 899 00:33:40,770 --> 00:33:42,780 that it, also, keeps these, 900 00:33:42,780 --> 00:33:44,970 overwritten environment variables? 901 00:33:44,970 --> 00:33:46,440 So, that is quite tricky. 902 00:33:46,440 --> 00:33:47,273 To my knowledge, 903 00:33:47,273 --> 00:33:50,580 you can't do that with an "LMK" file, for example. 904 00:33:50,580 --> 00:33:51,413 You could, of course, 905 00:33:51,413 --> 00:33:53,550 just use that "PowerShell" script or VBScripts 906 00:33:53,550 --> 00:33:54,660 and run that persistently. 907 00:33:54,660 --> 00:33:56,820 But that is not really persistent, is it? 908 00:33:56,820 --> 00:33:58,710 It sort of, like, it defies the whole point. 909 00:33:58,710 --> 00:34:01,440 You might, as well, undo the bad stuff in the script. 910 00:34:01,440 --> 00:34:03,120 what you could do, however, 911 00:34:03,120 --> 00:34:04,170 if you're already admin, 912 00:34:04,170 --> 00:34:06,480 if you, already, have elevated privileges, 913 00:34:06,480 --> 00:34:09,120 you could change a service. 914 00:34:09,120 --> 00:34:13,650 So, "Windows Services" is like daemons in "Linux", 915 00:34:13,650 --> 00:34:16,530 that allows you to start stuff persistently. 916 00:34:16,530 --> 00:34:17,760 So, the screenshot you see here, 917 00:34:17,760 --> 00:34:19,710 is from the printer spooler, 918 00:34:19,710 --> 00:34:22,743 which has started by default on "Windows 11" installations. 919 00:34:23,970 --> 00:34:28,970 There is a very underused or under-utilized registry value, 920 00:34:28,980 --> 00:34:31,080 you can say, called environment. 921 00:34:31,080 --> 00:34:32,250 And as you can guess, 922 00:34:32,250 --> 00:34:34,590 you can, literally, just specify environment variables 923 00:34:34,590 --> 00:34:35,423 in there 924 00:34:35,423 --> 00:34:38,681 that will be used in the scope of that service. 925 00:34:38,681 --> 00:34:39,514 (smacks lips) 926 00:34:39,514 --> 00:34:40,537 So, in this case, printer spooler, 927 00:34:40,537 --> 00:34:42,660 I just said, "SystemRoot", once again, 928 00:34:42,660 --> 00:34:45,300 I pointed it to my folder with all my implants 929 00:34:45,300 --> 00:34:47,790 and well, yeah, what do you think is gonna happen 930 00:34:47,790 --> 00:34:50,140 if I restart the servers or reboot the machine? 931 00:34:51,390 --> 00:34:54,060 Luckily enough, it's loaded one of my DLLs. 932 00:34:54,060 --> 00:34:56,187 It's the same one again, "mswsock". 933 00:34:57,660 --> 00:34:58,950 The great thing, however, 934 00:34:58,950 --> 00:35:01,410 is that it, now, also, runs it as system, 935 00:35:01,410 --> 00:35:02,820 most "Windows" services, not all of them, 936 00:35:02,820 --> 00:35:03,653 but most of them, 937 00:35:03,653 --> 00:35:06,210 run either with a service account, or system. 938 00:35:06,210 --> 00:35:09,180 So, it's not, really, privilege escalation, of course, 939 00:35:09,180 --> 00:35:10,290 but if you are admin 940 00:35:10,290 --> 00:35:12,210 and you want to elevate yourself to system 941 00:35:12,210 --> 00:35:14,370 in a stealthier way, 942 00:35:14,370 --> 00:35:16,380 this is a cool way of doing it. 943 00:35:16,380 --> 00:35:17,430 Because you could argue, right? 944 00:35:17,430 --> 00:35:18,840 If you, already, have admin, 945 00:35:18,840 --> 00:35:22,290 you might as well, just change the command of the servers. 946 00:35:22,290 --> 00:35:23,123 But that is something 947 00:35:23,123 --> 00:35:25,470 that "EDR" and "AV", typically, pick up on, 948 00:35:25,470 --> 00:35:26,910 whereas, this is, maybe, something 949 00:35:26,910 --> 00:35:28,310 that isn't really monitored. 950 00:35:29,460 --> 00:35:33,243 And again, if you implement the DLL properly, 951 00:35:34,080 --> 00:35:36,780 the printer spooler server would still work, right? 952 00:35:36,780 --> 00:35:38,760 It just, also, executes your malicious code. 953 00:35:38,760 --> 00:35:41,340 So, there's less scope of breaking stuff 954 00:35:41,340 --> 00:35:42,890 and therefore, it's stealthier. 955 00:35:44,640 --> 00:35:46,620 But yeah, coming back to privilege escalation, 956 00:35:46,620 --> 00:35:48,630 can you do real privilege escalation with this, 957 00:35:48,630 --> 00:35:51,273 or even "User Account Control" bypass? 958 00:35:52,380 --> 00:35:55,200 Now, this is where we come back to that earlier comment 959 00:35:55,200 --> 00:35:58,050 on security and "Microsoft" design. 960 00:35:58,050 --> 00:35:59,250 So, in the "Windows API", 961 00:35:59,250 --> 00:36:01,830 you have, generally, two ways of spawning a new process. 962 00:36:01,830 --> 00:36:04,860 You've got "CreateProcess" and "ShellExecute". 963 00:36:04,860 --> 00:36:07,020 The former cannot run programs 964 00:36:07,020 --> 00:36:10,950 that run with more privileges than yourself. 965 00:36:10,950 --> 00:36:12,870 So, if you are medium integrity, 966 00:36:12,870 --> 00:36:14,580 you can't get it to run high integrity, 967 00:36:14,580 --> 00:36:16,897 without doing something weird. 968 00:36:16,897 --> 00:36:18,510 "ShellExecute" can, 969 00:36:18,510 --> 00:36:20,100 but whenever you do that, 970 00:36:20,100 --> 00:36:23,760 it does not take your process-level environment variables. 971 00:36:23,760 --> 00:36:26,880 This seems to be a very conscious decision by "Microsoft" 972 00:36:26,880 --> 00:36:30,189 to limit the scope for privilege escalation. 973 00:36:30,189 --> 00:36:31,410 (smacks lips) 974 00:36:31,410 --> 00:36:35,040 Any process that is run with a higher integrity level, 975 00:36:35,040 --> 00:36:37,080 than the one it was spawned from, 976 00:36:37,080 --> 00:36:39,660 will, generally, just reset the environment variables 977 00:36:39,660 --> 00:36:43,084 to the one, defined on system-level or user-level 978 00:36:43,084 --> 00:36:45,210 (indistinct). 979 00:36:45,210 --> 00:36:46,290 This seems to be a reaction 980 00:36:46,290 --> 00:36:48,180 to that "PATH" environment variable thing 981 00:36:48,180 --> 00:36:50,010 that we mentioned at the very start. 982 00:36:50,010 --> 00:36:51,780 So, that caused a lot of trouble in the past 983 00:36:51,780 --> 00:36:53,497 and "Microsoft" decided, 984 00:36:53,497 --> 00:36:54,930 "No, we're gonna implement it this way," 985 00:36:54,930 --> 00:36:57,270 and that means there is less scope 986 00:36:57,270 --> 00:37:00,870 for environment-variable-based privilege escalation. 987 00:37:00,870 --> 00:37:01,830 And you gotta give it to them, 988 00:37:01,830 --> 00:37:03,210 because in this case, it does work, right? 989 00:37:03,210 --> 00:37:04,350 It does hold us back. 990 00:37:04,350 --> 00:37:06,750 It means, we can't do "User Account Control" bypass 991 00:37:06,750 --> 00:37:08,700 in the traditional way. 992 00:37:08,700 --> 00:37:09,930 What I will, however, say, 993 00:37:09,930 --> 00:37:13,560 is that there are a couple of anecdotal instances, 994 00:37:13,560 --> 00:37:16,890 where the executable that is spawned, 995 00:37:16,890 --> 00:37:19,080 is known to override this behavior. 996 00:37:19,080 --> 00:37:20,820 So, there's one or two that I've seen 997 00:37:20,820 --> 00:37:22,860 that, even though they are spawned 998 00:37:22,860 --> 00:37:24,630 with higher integrity level, 999 00:37:24,630 --> 00:37:27,840 they, still, manually copy back the environment variables 1000 00:37:27,840 --> 00:37:29,040 of the parent process, 1001 00:37:29,040 --> 00:37:30,960 sort of, overriding this behavior. 1002 00:37:30,960 --> 00:37:32,340 So, if that is the case, 1003 00:37:32,340 --> 00:37:34,140 you could, of course, still use this technique 1004 00:37:34,140 --> 00:37:35,463 for privilege escalation. 1005 00:37:37,536 --> 00:37:38,610 (smacks lips) 1006 00:37:38,610 --> 00:37:39,723 Okay, right. 1007 00:37:40,830 --> 00:37:41,760 So, final remarks. 1008 00:37:41,760 --> 00:37:42,690 What does this mean? 1009 00:37:42,690 --> 00:37:46,350 We've, now, looked at new type of DLL hijacking. 1010 00:37:46,350 --> 00:37:47,700 There's a couple of other ones. 1011 00:37:47,700 --> 00:37:49,890 What does the future hold? 1012 00:37:49,890 --> 00:37:50,820 I think, the bottom line, 1013 00:37:50,820 --> 00:37:52,230 is what I'm really trying to say here, 1014 00:37:52,230 --> 00:37:55,020 is that DLL hijacking is not gonna go away. 1015 00:37:55,020 --> 00:37:58,200 Even, if we magically fixed all these issues, 1016 00:37:58,200 --> 00:37:59,970 including the other variants, 1017 00:37:59,970 --> 00:38:02,700 we would, still, have to deal with this, deal with it, 1018 00:38:02,700 --> 00:38:05,070 because attackers could, still, bring in back, 1019 00:38:05,070 --> 00:38:06,810 these older versions, right? 1020 00:38:06,810 --> 00:38:10,290 I could, now, copy these "Windows 11" executables, 1021 00:38:10,290 --> 00:38:11,670 bring it to a fully-patched system 1022 00:38:11,670 --> 00:38:13,740 and you would, still, have to deal with the program, 1023 00:38:13,740 --> 00:38:15,240 because they're still signed, 1024 00:38:15,240 --> 00:38:18,090 they're still trusted and are still vulnerable. 1025 00:38:18,090 --> 00:38:21,420 So, I think, we need to learn to live with DLL hijacking 1026 00:38:21,420 --> 00:38:22,620 and from an offensive point of view, 1027 00:38:22,620 --> 00:38:25,260 it's all about like, making it stealthier, 1028 00:38:25,260 --> 00:38:26,820 from a defensive point of view, 1029 00:38:26,820 --> 00:38:29,043 it's all about like, limiting the scope. 1030 00:38:30,840 --> 00:38:32,700 So, in order to aid with that, 1031 00:38:32,700 --> 00:38:33,533 in the last few months, 1032 00:38:33,533 --> 00:38:37,740 I have tried to document all sorts of DLL hijacking types 1033 00:38:37,740 --> 00:38:38,700 that I could find 1034 00:38:38,700 --> 00:38:41,280 and centralize them in a curated repo. 1035 00:38:41,280 --> 00:38:42,900 So, as of this morning, 1036 00:38:42,900 --> 00:38:45,237 you can, now, go to "hijacklibs.net" 1037 00:38:45,237 --> 00:38:46,650 and you get a nice portal there 1038 00:38:46,650 --> 00:38:51,120 and you can find, not only the environment variable, 1039 00:38:51,120 --> 00:38:53,880 DLL hijacking ones, I've been talking about so far, 1040 00:38:53,880 --> 00:38:56,730 but also, other ones, you can, also, find side-loading, 1041 00:38:56,730 --> 00:38:59,463 phantom DLL hijacking, search order hijacking. 1042 00:39:00,840 --> 00:39:04,380 Yeah, as I said, I'm trying to make it more central. 1043 00:39:04,380 --> 00:39:07,290 Again, all the entries there, have public resources. 1044 00:39:07,290 --> 00:39:10,080 So, it has been blogged about before, tweeted about before, 1045 00:39:10,080 --> 00:39:11,550 but I'm trying to bring them together, 1046 00:39:11,550 --> 00:39:14,190 so, we can get a better idea of the scope 1047 00:39:14,190 --> 00:39:17,520 and see how you can use this or defend against it 1048 00:39:17,520 --> 00:39:19,410 if that's what you're after. 1049 00:39:19,410 --> 00:39:20,690 It's an open-source project. 1050 00:39:20,690 --> 00:39:23,310 I, really, hope that as a community, 1051 00:39:23,310 --> 00:39:25,740 we can, really, keep adding stuff to it, 1052 00:39:25,740 --> 00:39:27,270 to raise awareness for it, 1053 00:39:27,270 --> 00:39:29,400 again, both for offensive and defensive. 1054 00:39:29,400 --> 00:39:30,750 Because I think, there's a lot we can learn 1055 00:39:30,750 --> 00:39:32,732 from each other, there. 1056 00:39:32,732 --> 00:39:33,565 (smacks lips) 1057 00:39:33,565 --> 00:39:34,920 So, very basically, how does it work? 1058 00:39:34,920 --> 00:39:36,150 I've got a bit of a demo, as well, 1059 00:39:36,150 --> 00:39:39,120 but every vulnerable DLL that is known, 1060 00:39:39,120 --> 00:39:40,203 has its own entry. 1061 00:39:43,607 --> 00:39:45,480 It breaks down the types of DLL hijacking, 1062 00:39:45,480 --> 00:39:47,430 so, it could be environment-variable-based, 1063 00:39:47,430 --> 00:39:49,050 it could also be side-loading, 1064 00:39:49,050 --> 00:39:50,880 sometimes, it's both. 1065 00:39:50,880 --> 00:39:53,370 It tells you where the DLL is normally located, 1066 00:39:53,370 --> 00:39:55,860 it tells you what executable is normally located. 1067 00:39:55,860 --> 00:39:57,900 And for the blue team side, 1068 00:39:57,900 --> 00:40:00,240 you, also, get some very basic detection logic 1069 00:40:00,240 --> 00:40:02,126 that you could leverage. 1070 00:40:02,126 --> 00:40:02,959 (smacks lips) 1071 00:40:02,959 --> 00:40:04,920 So, let's take a quick look. 1072 00:40:04,920 --> 00:40:05,753 There we go. 1073 00:40:05,753 --> 00:40:08,580 So, on the front page, are listed a couple of new entries, 1074 00:40:08,580 --> 00:40:10,546 you can, also, browse by vendor. 1075 00:40:10,546 --> 00:40:11,379 In this case, 1076 00:40:11,379 --> 00:40:14,280 I'm gonna look up a specific DLL, I'm interested in. 1077 00:40:14,280 --> 00:40:16,590 It tells me there are two types of DLL hijacking, 1078 00:40:16,590 --> 00:40:19,380 search order hijacking and side-loading. 1079 00:40:19,380 --> 00:40:20,580 It gives me the resources, 1080 00:40:20,580 --> 00:40:22,260 so, if there's a blog or a tweet, 1081 00:40:22,260 --> 00:40:23,610 it can be really useful. 1082 00:40:23,610 --> 00:40:25,420 As I said, you can, now, see the paths 1083 00:40:25,420 --> 00:40:26,730 where you would, normally, see it 1084 00:40:26,730 --> 00:40:28,350 and then, it tells you 1085 00:40:28,350 --> 00:40:31,350 what executables are vulnerable, as well. 1086 00:40:31,350 --> 00:40:34,170 Yeah, here, you see some Sigma code, 1087 00:40:34,170 --> 00:40:37,863 some open-source format for defining detection rules. 1088 00:40:39,060 --> 00:40:41,610 If I, then, say, for example, look for a specific vendor, 1089 00:40:41,610 --> 00:40:42,810 so, this is "Trend Micro", 1090 00:40:42,810 --> 00:40:44,700 I can see some other stuff, as well. 1091 00:40:44,700 --> 00:40:47,310 So, this is a type of a phantom DLL hijacking 1092 00:40:47,310 --> 00:40:49,170 that, actually, had a "CVE" 1093 00:40:49,170 --> 00:40:50,430 and it tells you how you can use that 1094 00:40:50,430 --> 00:40:51,750 for privilege escalation. 1095 00:40:51,750 --> 00:40:53,580 Again, this is all public information, 1096 00:40:53,580 --> 00:40:54,510 it's all been talked about, 1097 00:40:54,510 --> 00:40:56,850 but it just helps you, sort of, understand 1098 00:40:56,850 --> 00:40:58,745 what options you have. 1099 00:40:58,745 --> 00:40:59,578 (smacks lips) 1100 00:40:59,578 --> 00:41:02,670 If you, very quickly, want to see everything, 1101 00:41:02,670 --> 00:41:04,080 just type ".exe", 1102 00:41:04,080 --> 00:41:06,663 you get all the mappings between a DLL 1103 00:41:06,663 --> 00:41:08,550 and a vulnerable executables 1104 00:41:08,550 --> 00:41:10,620 that you could leverage for that. 1105 00:41:10,620 --> 00:41:13,620 And yep, that's the end of the demo. 1106 00:41:13,620 --> 00:41:15,240 So, as I was saying, 1107 00:41:15,240 --> 00:41:17,520 I'm about to wrap up, 1108 00:41:17,520 --> 00:41:19,170 it's, now, live, "hijacklibs.net". 1109 00:41:19,170 --> 00:41:20,250 It's an open-source project, 1110 00:41:20,250 --> 00:41:21,450 it's all on "GitHub", 1111 00:41:21,450 --> 00:41:23,037 it is hosted in "GitHub", as well. 1112 00:41:23,037 --> 00:41:24,750 So, if you have any new entries, 1113 00:41:24,750 --> 00:41:25,710 or if you wanna improve, 1114 00:41:25,710 --> 00:41:27,600 or wanna help this project, 1115 00:41:27,600 --> 00:41:28,860 to keep this project going, 1116 00:41:28,860 --> 00:41:30,840 please do contribute. 1117 00:41:30,840 --> 00:41:33,000 If you go to the website, there is a link to the repo, 1118 00:41:33,000 --> 00:41:34,653 where you can find more. 1119 00:41:36,840 --> 00:41:38,460 And that is what I had to share with you, today. 1120 00:41:38,460 --> 00:41:40,740 I, really, hope that was useful. 1121 00:41:40,740 --> 00:41:41,573 If you have any feedback, 1122 00:41:41,573 --> 00:41:43,410 obviously, come find me afterwards here at the stage, 1123 00:41:43,410 --> 00:41:44,580 or follow me on "Twitter". 1124 00:41:44,580 --> 00:41:46,770 My Dms are open, "@Wietze" 1125 00:41:46,770 --> 00:41:49,990 and thank you very much for showing up on Sunday morning. 1126 00:41:49,990 --> 00:41:51,768 (audience applauds)