1 00:00:00,150 --> 00:00:01,650 - Welcome to track three. 2 00:00:01,650 --> 00:00:05,070 And our three o'clock is a new speaker. 3 00:00:05,070 --> 00:00:07,941 So first time speaking, what does that mean? 4 00:00:07,941 --> 00:00:11,130 (audience applauds and cheers) 5 00:00:11,130 --> 00:00:14,520 So let's start off with saying l'chaim to Ron 6 00:00:14,520 --> 00:00:16,143 and l'chaim! 7 00:00:18,207 --> 00:00:22,124 (audience applauds and cheers) 8 00:00:25,091 --> 00:00:26,430 (Ron clears his throat) 9 00:00:26,430 --> 00:00:27,359 - Hello everyone. 10 00:00:27,359 --> 00:00:30,090 Today, I will talk with you about a new method to 11 00:00:30,090 --> 00:00:33,720 dump the memory of LSASS, (clears throat) 12 00:00:33,720 --> 00:00:35,910 which is called LSASS Shtinkering. 13 00:00:35,910 --> 00:00:37,050 In case you don't know 14 00:00:37,050 --> 00:00:40,260 shtinker is a Hebrew word for snitch 15 00:00:40,260 --> 00:00:43,336 and this is the reason behind the name of this method. 16 00:00:43,336 --> 00:00:44,193 (coughs) Sorry. 17 00:00:45,386 --> 00:00:48,360 (crowd laughs and cheers) 18 00:00:48,360 --> 00:00:50,033 We're going to snitch on LSASS. 19 00:00:51,660 --> 00:00:54,720 And we all know the phrase "snitches get stitches", 20 00:00:54,720 --> 00:00:57,393 but luckily, no one will know this is us. 21 00:00:59,340 --> 00:01:01,320 So a little bit about us. 22 00:01:01,320 --> 00:01:04,050 This method was discovered by Asaf Gilboa, 23 00:01:04,050 --> 00:01:05,970 a friend and a colleague of mine. 24 00:01:05,970 --> 00:01:08,190 Unfortunately, he couldn't join us today. 25 00:01:08,190 --> 00:01:10,260 And my name is Ron Ben-Yitzhak. 26 00:01:10,260 --> 00:01:12,483 I'm a security researcher at Deep Instinct. 27 00:01:14,070 --> 00:01:15,595 And a fun fact about me, 28 00:01:15,595 --> 00:01:17,670 last night I lost three-hundred dollars 29 00:01:17,670 --> 00:01:18,951 at the casino. 30 00:01:18,951 --> 00:01:23,130 (audience and Ron laugh) 31 00:01:23,130 --> 00:01:25,500 So this is the agenda for this talk. 32 00:01:25,500 --> 00:01:26,910 I'll start with an overview 33 00:01:26,910 --> 00:01:28,980 about credential lobbying attacks. 34 00:01:28,980 --> 00:01:30,270 I'll go over known memory 35 00:01:30,270 --> 00:01:32,790 dumping techniques and common tools. 36 00:01:32,790 --> 00:01:33,623 Then, I'll explain 37 00:01:33,623 --> 00:01:35,400 how this method was discovered 38 00:01:35,400 --> 00:01:37,500 by reverse engineering the client side 39 00:01:37,500 --> 00:01:40,680 of the Windows LLL reporting mechanism. (clears throat) 40 00:01:40,680 --> 00:01:43,710 Then I'll talk about reverse engineering the server side, 41 00:01:43,710 --> 00:01:46,710 and I'll finish with ways to detect and prevent this attack. 42 00:01:49,140 --> 00:01:51,870 So credential access is a huge subject. 43 00:01:51,870 --> 00:01:54,150 It's a whole tactic in the MITRE Matrix. 44 00:01:54,150 --> 00:01:55,410 And on this screenshot 45 00:01:55,410 --> 00:01:58,650 you can see all the techniques under this tactic. 46 00:01:58,650 --> 00:01:59,790 In this circle, focus 47 00:01:59,790 --> 00:02:01,833 on the LSASS memory sub-technique. 48 00:02:03,210 --> 00:02:05,340 Credentials are important for attackers. 49 00:02:05,340 --> 00:02:07,320 They use it to move across the network, 50 00:02:07,320 --> 00:02:08,400 spread their tools 51 00:02:08,400 --> 00:02:10,830 and usually their ransomware. 52 00:02:10,830 --> 00:02:13,020 And harvesting right credentials, 53 00:02:13,020 --> 00:02:16,170 is a simple way to log into other systems. 54 00:02:16,170 --> 00:02:19,230 It doesn't require exploiting vulnerabilities. 55 00:02:19,230 --> 00:02:21,210 And the holy grail for attackers, 56 00:02:21,210 --> 00:02:22,953 is the domain controller. 57 00:02:25,072 --> 00:02:27,468 Credential access is constantly used 58 00:02:27,468 --> 00:02:29,970 in actual attacks in the wild. 59 00:02:29,970 --> 00:02:33,450 And here you can see reports from multiple security vendors 60 00:02:33,450 --> 00:02:35,790 about some of the most infamous groups today 61 00:02:35,790 --> 00:02:38,730 that use credential dumping as part of their attacks. 62 00:02:38,730 --> 00:02:41,370 You can see reports about Conti, BlackCats, 63 00:02:41,370 --> 00:02:43,173 Lockbits and many more. 64 00:02:44,250 --> 00:02:47,550 But how does the credential dumping attack go? 65 00:02:47,550 --> 00:02:50,580 So, once a user has logged onto the system 66 00:02:50,580 --> 00:02:51,870 their credentials are stored 67 00:02:51,870 --> 00:02:53,610 in the memory of LSASS. 68 00:02:53,610 --> 00:02:56,190 This memory can be read and written to disk, 69 00:02:56,190 --> 00:02:58,680 then passed by its tools like Mimikatz. 70 00:02:58,680 --> 00:03:00,300 The credentials are extracted 71 00:03:00,300 --> 00:03:02,103 and used for lateral movement. 72 00:03:03,630 --> 00:03:05,670 So a little bit about LSASS. 73 00:03:05,670 --> 00:03:08,620 The Local Security Authority Subsystem Service. 74 00:03:08,620 --> 00:03:10,980 It is a system process that is responsible 75 00:03:10,980 --> 00:03:14,490 for authenticating users and verifying logons. 76 00:03:14,490 --> 00:03:16,140 And the problem with it 77 00:03:16,140 --> 00:03:18,660 is that it works as a single sign on. 78 00:03:18,660 --> 00:03:20,880 Like I said, the user logs in once 79 00:03:20,880 --> 00:03:22,260 and the credentials are stored 80 00:03:22,260 --> 00:03:24,030 in the memory of this process. 81 00:03:24,030 --> 00:03:27,630 And this memory can be dumped to disk by other processes 82 00:03:27,630 --> 00:03:30,123 with APIs like MiniDumpWriteDump. 83 00:03:32,580 --> 00:03:33,930 Another thing we should talk about 84 00:03:33,930 --> 00:03:36,450 is the Windows Error Reporting Service. 85 00:03:36,450 --> 00:03:39,900 It is a building component of the Windows operating system. 86 00:03:39,900 --> 00:03:41,700 It collects information about processes 87 00:03:41,700 --> 00:03:43,800 that are an unhandled exception 88 00:03:43,800 --> 00:03:47,040 and can create memory dumps of those processes. 89 00:03:47,040 --> 00:03:48,810 We already looked into the service 90 00:03:48,810 --> 00:03:51,720 as a part of a as part of our previous research 91 00:03:51,720 --> 00:03:53,550 that I'll talk about soon. 92 00:03:53,550 --> 00:03:56,250 And that the target of this research was to 93 00:03:56,250 --> 00:03:59,730 find a new way to perform a credential dumping attack. 94 00:03:59,730 --> 00:04:02,070 We wanted to force this service 95 00:04:02,070 --> 00:04:04,410 to dump the memory of LSASS for us, 96 00:04:04,410 --> 00:04:06,360 and that way we'll have a stealthy way 97 00:04:06,360 --> 00:04:08,163 to evade EDR solutions. 98 00:04:09,840 --> 00:04:12,570 Now, let's talk about some existing dumping techniques. 99 00:04:12,570 --> 00:04:15,450 The first one is using the tool ProcDump 100 00:04:15,450 --> 00:04:16,950 which is part of Sysinternals. 101 00:04:18,000 --> 00:04:20,100 It can dump the memory of LSASS 102 00:04:20,100 --> 00:04:21,750 with the following command line. 103 00:04:21,750 --> 00:04:23,970 Here is the example for that. 104 00:04:23,970 --> 00:04:28,660 And another way to do that is by using the DLL comsvcx. 105 00:04:29,640 --> 00:04:31,170 It doesn't expose this function 106 00:04:31,170 --> 00:04:32,670 which is called Minidump. 107 00:04:32,670 --> 00:04:34,760 You can supply the process ID of LSASS 108 00:04:34,760 --> 00:04:36,030 to this function 109 00:04:36,030 --> 00:04:37,800 and it will do the work for us. 110 00:04:37,800 --> 00:04:39,800 And here is an example for that as well. 111 00:04:42,330 --> 00:04:46,110 Another easy way is to just use the task manager. 112 00:04:46,110 --> 00:04:47,850 We can right click on the process 113 00:04:47,850 --> 00:04:49,713 and select create dump file. 114 00:04:51,270 --> 00:04:53,250 Now, another method we should talk about 115 00:04:53,250 --> 00:04:54,750 is Silent Process Exit 116 00:04:54,750 --> 00:04:57,000 which was also discovered by us, 117 00:04:57,000 --> 00:04:58,950 and it is a documented mechanism 118 00:04:58,950 --> 00:05:01,230 that was introduced in Windows 7. 119 00:05:01,230 --> 00:05:03,510 It is activated when a process terminates 120 00:05:03,510 --> 00:05:05,520 and it can do one of the following: 121 00:05:05,520 --> 00:05:06,900 show a message box, 122 00:05:06,900 --> 00:05:08,430 launch a new process, 123 00:05:08,430 --> 00:05:10,290 or create a dump file. 124 00:05:10,290 --> 00:05:13,440 You can configure this mechanism by using the registry. 125 00:05:13,440 --> 00:05:16,110 Simply create the keys and the values for the process 126 00:05:16,110 --> 00:05:18,090 this mechanism should operate on 127 00:05:18,090 --> 00:05:22,620 and trigger it by calling RtlReportSilentProcessExit. 128 00:05:22,620 --> 00:05:25,650 And this is the research I mentioned earlier. 129 00:05:25,650 --> 00:05:27,630 Behind the scenes it communicates 130 00:05:27,630 --> 00:05:30,570 with the Windows Error Reporting Service. 131 00:05:30,570 --> 00:05:32,670 And also for the rest of this talk, 132 00:05:32,670 --> 00:05:35,523 I'll refer to this service as the WERS Service. 133 00:05:37,530 --> 00:05:39,240 Now I have to show off a little bit. 134 00:05:39,240 --> 00:05:41,580 So, this method caught the attention 135 00:05:41,580 --> 00:05:45,000 of Benjamin Delpy, Florian Roth 136 00:05:45,000 --> 00:05:47,520 and also already two that have tested it 137 00:05:47,520 --> 00:05:49,530 against their security product 138 00:05:49,530 --> 00:05:51,213 and it completely bypassed it. 139 00:05:53,100 --> 00:05:54,930 But there are protections against 140 00:05:54,930 --> 00:05:56,820 dumping the memory of LSASS, 141 00:05:56,820 --> 00:06:00,450 such as protected process slides or PPL. 142 00:06:00,450 --> 00:06:01,860 This is a security mechanism 143 00:06:01,860 --> 00:06:03,660 in Windows that prevents tampering 144 00:06:03,660 --> 00:06:05,703 with sensitive processes. 145 00:06:06,630 --> 00:06:09,480 A flag is setting the kernel for the protected process 146 00:06:09,480 --> 00:06:11,310 and it restricts the access that 147 00:06:11,310 --> 00:06:13,233 the regular process can gain on it. 148 00:06:15,360 --> 00:06:16,950 And this can be set as a PPL 149 00:06:16,950 --> 00:06:18,810 with a single registered value 150 00:06:18,810 --> 00:06:20,910 and that will prevent other processes 151 00:06:20,910 --> 00:06:22,080 from gaining a handle 152 00:06:22,080 --> 00:06:24,210 with the permission of VM Wid. 153 00:06:24,210 --> 00:06:25,650 The permission that is required 154 00:06:25,650 --> 00:06:28,560 for reading the memory of another process. 155 00:06:28,560 --> 00:06:33,560 So you might be thinking that PPL is a perfect solution, 156 00:06:34,320 --> 00:06:36,780 but there is a problem with it 157 00:06:36,780 --> 00:06:37,621 especially for enterprises 158 00:06:37,621 --> 00:06:39,843 and large networks. 159 00:06:40,890 --> 00:06:42,810 It prevents third party DLL files 160 00:06:42,810 --> 00:06:44,588 from loading into LSASS. 161 00:06:44,588 --> 00:06:46,770 That means that benign authentication packages 162 00:06:46,770 --> 00:06:48,930 and plugins cannot be used. 163 00:06:48,930 --> 00:06:51,240 It can cause issues when there are many solutions 164 00:06:51,240 --> 00:06:53,790 and products that are installed in the network 165 00:06:53,790 --> 00:06:56,343 and that is why some organizations don't use it. 166 00:06:57,750 --> 00:07:00,720 So we talked about several dumping techniques 167 00:07:00,720 --> 00:07:02,280 and they all have issues. 168 00:07:02,280 --> 00:07:03,810 They're easy to identify, 169 00:07:03,810 --> 00:07:05,430 either by the command line 170 00:07:05,430 --> 00:07:07,470 or the APIs they use. 171 00:07:07,470 --> 00:07:09,510 And also some of the tools might be blocked 172 00:07:09,510 --> 00:07:11,790 by security products. 173 00:07:11,790 --> 00:07:16,200 So, now let's talk about LSASS Shtinkering. 174 00:07:16,200 --> 00:07:17,760 Like I said, it is a new method 175 00:07:17,760 --> 00:07:19,290 to dump the memory of LSASS, 176 00:07:19,290 --> 00:07:22,020 and it doesn't use a vulnerability. 177 00:07:22,020 --> 00:07:24,240 It abuses the service we talked about, 178 00:07:24,240 --> 00:07:26,670 the Windows Error Reporting Service. 179 00:07:26,670 --> 00:07:28,620 We're going to manually report an error 180 00:07:28,620 --> 00:07:31,200 to this service that will make it think 181 00:07:31,200 --> 00:07:34,080 that an exception occurred inside LSASS. 182 00:07:34,080 --> 00:07:36,480 Then it will produce a memory dump for us 183 00:07:36,480 --> 00:07:37,773 without terminating it. 184 00:07:39,030 --> 00:07:41,850 This will bypass security products that allow processes 185 00:07:41,850 --> 00:07:44,793 like Werfaults to dump the memory of LSASS. 186 00:07:47,520 --> 00:07:50,460 This is an abstract of what is going to happen. 187 00:07:50,460 --> 00:07:52,260 We're going to create a message, 188 00:07:52,260 --> 00:07:54,060 then start the service, 189 00:07:54,060 --> 00:07:56,520 send the message to the service. 190 00:07:56,520 --> 00:07:57,480 It's going to process 191 00:07:57,480 --> 00:07:58,470 and validate it 192 00:07:58,470 --> 00:08:00,453 and hopefully perform the dump. 193 00:08:02,459 --> 00:08:05,220 What is required for the dumping procedure is 194 00:08:05,220 --> 00:08:07,830 an inheritable process handle with VMware 195 00:08:07,830 --> 00:08:09,780 and query limited information. 196 00:08:09,780 --> 00:08:11,970 Also an inheritable threat handle 197 00:08:11,970 --> 00:08:14,430 with query limited information 198 00:08:14,430 --> 00:08:16,980 and the final require final requirements 199 00:08:16,980 --> 00:08:19,650 is setting the register value dump type 200 00:08:19,650 --> 00:08:22,683 under the LocalDumps key to full dump. 201 00:08:25,080 --> 00:08:27,630 Now, let's see what happens when a process crashes. 202 00:08:28,830 --> 00:08:31,590 This process tries to read out of zero 203 00:08:31,590 --> 00:08:33,690 WerFault fault spawns the child process 204 00:08:33,690 --> 00:08:35,253 and produces a memory dump. 205 00:08:37,260 --> 00:08:40,020 But what happened behind the scenes? 206 00:08:40,020 --> 00:08:42,480 Every process has exception endos. 207 00:08:42,480 --> 00:08:45,600 And the last one is called C Specific Handler. 208 00:08:45,600 --> 00:08:47,820 It is implemented inside ntdll, 209 00:08:47,820 --> 00:08:50,970 and it is responsible for two things. 210 00:08:50,970 --> 00:08:53,190 The first one is reporting the exception details 211 00:08:53,190 --> 00:08:55,110 to the WER Service. 212 00:08:55,110 --> 00:08:59,010 It does that by calling NtAlpcSendWaitReceivePorts. 213 00:08:59,010 --> 00:09:02,373 And the second thing is terminating the process. 214 00:09:03,270 --> 00:09:05,670 So that raises a question, 215 00:09:05,670 --> 00:09:09,330 can we report an exception on our own process? 216 00:09:09,330 --> 00:09:13,860 And turns out their service won't terminate our process. 217 00:09:13,860 --> 00:09:16,383 The responsibility for terminating a process 218 00:09:16,383 --> 00:09:19,740 that crashes is on the process itself. 219 00:09:19,740 --> 00:09:21,660 So how do we do that? 220 00:09:21,660 --> 00:09:25,203 How do we report an exception on our own process? 221 00:09:26,280 --> 00:09:28,860 To understand that we need to reverse engineer 222 00:09:28,860 --> 00:09:30,453 the client side of WER. 223 00:09:32,310 --> 00:09:33,630 Sorry. 224 00:09:33,630 --> 00:09:34,920 I'll start with explaining 225 00:09:34,920 --> 00:09:36,750 how to create a message. 226 00:09:36,750 --> 00:09:37,583 Then we'll see 227 00:09:37,583 --> 00:09:38,760 how to send a message 228 00:09:38,760 --> 00:09:40,050 and eventually we'll do that 229 00:09:40,050 --> 00:09:41,403 and see what happens. 230 00:09:43,800 --> 00:09:46,890 So the function WER peer report fault internal is 231 00:09:46,890 --> 00:09:49,740 responsible for creating a message. 232 00:09:49,740 --> 00:09:53,070 It starts with creating two unnamed events. 233 00:09:53,070 --> 00:09:55,470 These events will be used by the service. 234 00:09:55,470 --> 00:09:58,320 It will signal them to communicate with the clients. 235 00:09:58,320 --> 00:10:01,650 The next step is creating an unnamed file mapping 236 00:10:01,650 --> 00:10:03,870 with the protection of red lights. 237 00:10:03,870 --> 00:10:06,714 This mapping is then opened into a view. 238 00:10:06,714 --> 00:10:10,080 The step after that is duplicating the pseudo handlers 239 00:10:10,080 --> 00:10:12,273 for the process and the thread. 240 00:10:13,410 --> 00:10:15,360 Then all those values are written 241 00:10:15,360 --> 00:10:18,423 into the file mapping as an undocumented stocks. 242 00:10:19,560 --> 00:10:21,180 Those values are also sent 243 00:10:21,180 --> 00:10:23,940 to the FunctionReportExceptionInternal 244 00:10:23,940 --> 00:10:27,000 which stores them in another undocumented stocks 245 00:10:27,000 --> 00:10:28,770 and sends it to the function, 246 00:10:28,770 --> 00:10:30,243 send message to WER Service. 247 00:10:32,880 --> 00:10:34,890 But before we send a message 248 00:10:34,890 --> 00:10:38,100 let's understand how the communication 249 00:10:38,100 --> 00:10:38,933 between the client 250 00:10:38,933 --> 00:10:40,440 and the server work. 251 00:10:40,440 --> 00:10:42,270 So the communication is done 252 00:10:42,270 --> 00:10:44,550 with the advanced local procedure call 253 00:10:44,550 --> 00:10:46,830 or the LPC protocol. 254 00:10:46,830 --> 00:10:49,110 It is an undocumented IPC mechanism, 255 00:10:49,110 --> 00:10:51,330 which is used by RPC. 256 00:10:51,330 --> 00:10:52,163 And on the client's side, 257 00:10:52,163 --> 00:10:53,919 there are two important functions. 258 00:10:53,919 --> 00:10:56,490 The first function receives a string 259 00:10:56,490 --> 00:10:58,140 that represents the server 260 00:10:58,140 --> 00:11:00,060 and retains a port endo. 261 00:11:00,060 --> 00:11:03,510 The second function is called NtAlpcSendWaitReceivePorts 262 00:11:03,510 --> 00:11:04,950 and it uses the port end 263 00:11:04,950 --> 00:11:06,720 to send the message to the service 264 00:11:06,720 --> 00:11:08,223 and receive a message back. 265 00:11:10,410 --> 00:11:12,390 The next function we're going to talk about 266 00:11:12,390 --> 00:11:14,970 is send message to WER Service. 267 00:11:14,970 --> 00:11:16,440 Before the message is sent, 268 00:11:16,440 --> 00:11:19,170 we need to make sure the service is running. 269 00:11:19,170 --> 00:11:20,370 So this is done 270 00:11:20,370 --> 00:11:23,730 by calling anti updates WNF state data 271 00:11:23,730 --> 00:11:28,140 with the parameter WNF WER Service starts. 272 00:11:28,140 --> 00:11:30,360 Then we signal the service, 273 00:11:30,360 --> 00:11:32,280 it starts initializing, 274 00:11:32,280 --> 00:11:36,510 And once the event system error report's ready signaled, 275 00:11:36,510 --> 00:11:38,660 we know that the service is up and running. 276 00:11:39,720 --> 00:11:42,570 The next step will be using the string 277 00:11:42,570 --> 00:11:45,090 Windows Error Reporting Service ports 278 00:11:45,090 --> 00:11:47,700 to connect to the LPC ports. 279 00:11:47,700 --> 00:11:50,910 And finally, we can send a message. 280 00:11:50,910 --> 00:11:52,713 So let's try to do that. 281 00:11:56,070 --> 00:11:58,530 We're reporting an exception on our own process. 282 00:11:58,530 --> 00:12:00,330 The POC tool is launched 283 00:12:00,330 --> 00:12:03,630 WerFault spawns as a child process. 284 00:12:03,630 --> 00:12:04,860 We wait for it to finish 285 00:12:04,860 --> 00:12:07,020 and a memory dump is produced. 286 00:12:07,020 --> 00:12:10,773 And also the tool continues to execute until it exits. 287 00:12:12,420 --> 00:12:13,980 So, let's talk a little bit more 288 00:12:13,980 --> 00:12:16,140 about what happened in this demo. 289 00:12:16,140 --> 00:12:18,000 When the service receives the request 290 00:12:18,000 --> 00:12:19,980 it duplicates the file mapping handle to 291 00:12:19,980 --> 00:12:23,790 access the undocumented stock that was written into it. 292 00:12:23,790 --> 00:12:27,060 And also two instances of WerFault were spawned. 293 00:12:27,060 --> 00:12:29,040 The first instance is spawned 294 00:12:29,040 --> 00:12:31,350 under the service itself 295 00:12:31,350 --> 00:12:32,183 and the command line 296 00:12:32,183 --> 00:12:35,130 of this instance, specifies the file mapping handle 297 00:12:35,130 --> 00:12:37,500 the idea of the process that is being reported on, 298 00:12:37,500 --> 00:12:40,740 and the idea of the process that sent the request. 299 00:12:40,740 --> 00:12:41,790 The second instance of 300 00:12:41,790 --> 00:12:42,922 WerFault is spawned 301 00:12:42,922 --> 00:12:45,240 under the process that sent the request 302 00:12:45,240 --> 00:12:47,760 by calling create processes user. 303 00:12:47,760 --> 00:12:49,890 And this will be the process that eventually 304 00:12:49,890 --> 00:12:51,450 calls MiniDumpWriteDump 305 00:12:51,450 --> 00:12:54,003 and report the exception details to the event log. 306 00:12:55,020 --> 00:12:59,040 So, now we know how to send report an exception. 307 00:12:59,040 --> 00:13:01,530 So let's try to report on LSASS. 308 00:13:01,530 --> 00:13:03,420 We can just change the process ID 309 00:13:03,420 --> 00:13:04,290 and the handle. 310 00:13:04,290 --> 00:13:06,063 So let's see what happens. 311 00:13:08,040 --> 00:13:09,250 We launch our tool 312 00:13:10,260 --> 00:13:11,400 but it fails 313 00:13:11,400 --> 00:13:13,293 and it specifies an error code. 314 00:13:17,550 --> 00:13:19,770 So, what happened? 315 00:13:19,770 --> 00:13:21,480 The message back from the service 316 00:13:21,480 --> 00:13:22,740 specified an error code 317 00:13:22,740 --> 00:13:24,510 which means access denied. 318 00:13:24,510 --> 00:13:26,280 And to understand why we got that, 319 00:13:26,280 --> 00:13:29,163 we needed to reverse engineer the service side of WER. 320 00:13:30,780 --> 00:13:33,300 I'll start with an overview about the service, 321 00:13:33,300 --> 00:13:35,670 then we'll see where the error code came from 322 00:13:35,670 --> 00:13:36,750 and what we need to do 323 00:13:36,750 --> 00:13:40,093 to pass the validation checks performed by the service. 324 00:13:42,207 --> 00:13:46,140 The WER Service is implemented inside WerSvc.dll 325 00:13:46,140 --> 00:13:49,023 which means it is executed under svchost. 326 00:13:50,253 --> 00:13:52,920 This service is also set to manual starts 327 00:13:52,920 --> 00:13:55,890 which is why we needed to signal it first. 328 00:13:55,890 --> 00:13:57,840 The information about programs that crashed 329 00:13:57,840 --> 00:13:59,160 is sent to the service, 330 00:13:59,160 --> 00:14:00,480 and the logs that are produced 331 00:14:00,480 --> 00:14:02,133 will be used for diagnostics. 332 00:14:04,320 --> 00:14:06,450 The service initialization process happens 333 00:14:06,450 --> 00:14:09,690 inside the function start LPC server 334 00:14:09,690 --> 00:14:12,150 and we can see this function uses the string 335 00:14:12,150 --> 00:14:13,423 WER already saw, 336 00:14:13,423 --> 00:14:16,050 WindowsErrorReportingServicePorts. 337 00:14:16,050 --> 00:14:18,420 This string will be part of a stock 338 00:14:18,420 --> 00:14:20,070 called object attributes. 339 00:14:20,070 --> 00:14:24,960 And this stock will be sent to LPC, create ports. 340 00:14:24,960 --> 00:14:25,793 And also the next step 341 00:14:25,793 --> 00:14:28,320 in the initialization is creating a thread 342 00:14:28,320 --> 00:14:31,143 for the function static LPC server thread. 343 00:14:33,090 --> 00:14:36,513 This function will process incoming LPC messages. 344 00:14:37,950 --> 00:14:39,360 So now let's see 345 00:14:39,360 --> 00:14:41,160 why we got that error code. 346 00:14:41,160 --> 00:14:43,410 To find that out we search for references 347 00:14:43,410 --> 00:14:45,063 inside a code for this value. 348 00:14:46,260 --> 00:14:48,780 We place the break points on each reference 349 00:14:48,780 --> 00:14:51,330 and executed the service. 350 00:14:51,330 --> 00:14:53,550 The back one that hits is inside the function, 351 00:14:53,550 --> 00:14:55,593 check if system connecting to ports. 352 00:14:57,240 --> 00:14:59,460 So what is this function? 353 00:14:59,460 --> 00:15:01,093 The first thing it does is calling 354 00:15:01,093 --> 00:15:03,120 ImpersonateLoggedOnUser. 355 00:15:03,120 --> 00:15:05,880 The third that tenders our request is executed 356 00:15:05,880 --> 00:15:08,250 under the same user as the service, 357 00:15:08,250 --> 00:15:10,590 which is anti authority system. 358 00:15:10,590 --> 00:15:13,830 But after the impersonation, it will be executed 359 00:15:13,830 --> 00:15:14,970 under the same user 360 00:15:14,970 --> 00:15:17,193 as the process that sent the request. 361 00:15:18,420 --> 00:15:20,730 Then it tries to open the events, 362 00:15:20,730 --> 00:15:23,400 worse we see is system permission event 363 00:15:23,400 --> 00:15:24,810 but that call fails 364 00:15:24,810 --> 00:15:26,790 with the old code access denied 365 00:15:26,790 --> 00:15:29,250 which causes our request to fail. 366 00:15:29,250 --> 00:15:31,680 So what is so special about this event? 367 00:15:31,680 --> 00:15:32,883 Why can't we access it? 368 00:15:35,340 --> 00:15:36,637 To learn more about this event 369 00:15:36,637 --> 00:15:39,960 we search for other references to that string. 370 00:15:39,960 --> 00:15:43,500 It is referenced inside a function, start LPC server. 371 00:15:43,500 --> 00:15:46,350 The same function that initializes the service. 372 00:15:46,350 --> 00:15:48,723 And here we can see the creation of it. 373 00:15:49,770 --> 00:15:50,603 It is created 374 00:15:50,603 --> 00:15:52,020 with a security descriptor 375 00:15:52,020 --> 00:15:55,050 that specifies generic grid 376 00:15:55,050 --> 00:15:57,090 to the system user. 377 00:15:57,090 --> 00:16:01,200 but there is also another special thing about this event. 378 00:16:01,200 --> 00:16:02,853 It has a prefix. 379 00:16:04,500 --> 00:16:06,690 So now we need to understand 380 00:16:06,690 --> 00:16:08,250 what is the purpose of this prefix? 381 00:16:08,250 --> 00:16:09,660 So guess what we did. 382 00:16:09,660 --> 00:16:12,810 We searched for other references to that string. 383 00:16:12,810 --> 00:16:14,520 It is referenced inside a function 384 00:16:14,520 --> 00:16:16,443 create private name space. 385 00:16:18,210 --> 00:16:20,580 Now let's understand what are those. 386 00:16:20,580 --> 00:16:22,050 Private name spaces are used 387 00:16:22,050 --> 00:16:23,970 with objects called boundary descriptors 388 00:16:23,970 --> 00:16:26,460 to protect from a squatting attack. 389 00:16:26,460 --> 00:16:28,230 This is a denial of service attack 390 00:16:28,230 --> 00:16:29,098 where one program interface 391 00:16:29,098 --> 00:16:31,860 with the execution of another program 392 00:16:31,860 --> 00:16:34,770 by using shared synchronization objects, 393 00:16:34,770 --> 00:16:35,899 or in other words 394 00:16:35,899 --> 00:16:39,000 unprivileged application creates the objects 395 00:16:39,000 --> 00:16:41,100 before the privileged application 396 00:16:41,100 --> 00:16:44,550 thus denying access to the legitimate one. 397 00:16:44,550 --> 00:16:47,070 And here is an example for that. 398 00:16:47,070 --> 00:16:48,990 Let's say we have a malware 399 00:16:48,990 --> 00:16:52,530 and an EDR agent executing on the same system. 400 00:16:52,530 --> 00:16:55,800 The model executes first as a low privilege process, 401 00:16:55,800 --> 00:16:59,550 and then the EDR agent starts as a privileged one. 402 00:16:59,550 --> 00:17:03,030 The malware tries to create the Mutex service Mutex 403 00:17:03,030 --> 00:17:04,020 and it is the first one 404 00:17:04,020 --> 00:17:05,430 to try to do so, 405 00:17:05,430 --> 00:17:08,880 so it will be successful. 406 00:17:08,880 --> 00:17:11,760 And then it starts doing malicious stuff. 407 00:17:11,760 --> 00:17:13,770 Then the EDR agent starts, 408 00:17:13,770 --> 00:17:15,927 it tries to create the same Mutex 409 00:17:15,927 --> 00:17:19,140 but the error code will be already existing, 410 00:17:19,140 --> 00:17:20,823 and then it will exit. 411 00:17:21,900 --> 00:17:26,463 So how those objects protect from this attack? 412 00:17:27,360 --> 00:17:29,520 Private name spaces are like directory 413 00:17:29,520 --> 00:17:31,410 for kernel objects. 414 00:17:31,410 --> 00:17:33,300 Kernel objects that are created inside 415 00:17:33,300 --> 00:17:34,800 this directory are protected 416 00:17:34,800 --> 00:17:36,960 by boundary descriptors. 417 00:17:36,960 --> 00:17:39,540 And those descriptors contain 418 00:17:39,540 --> 00:17:41,280 the security IDs for the users 419 00:17:41,280 --> 00:17:43,380 in the groups that are allowed to create objects 420 00:17:43,380 --> 00:17:44,613 inside this directory. 421 00:17:45,630 --> 00:17:49,530 Another important thing is that name spaces are identified 422 00:17:49,530 --> 00:17:51,720 by both the name, the string, 423 00:17:51,720 --> 00:17:53,910 and the boundary descriptor. 424 00:17:53,910 --> 00:17:56,370 This means that different name spaces can have 425 00:17:56,370 --> 00:17:57,240 the same name, 426 00:17:57,240 --> 00:17:59,820 but different boundary descriptors. 427 00:17:59,820 --> 00:18:02,370 So let's look at the example again. 428 00:18:02,370 --> 00:18:04,260 But this time the mutex is granted 429 00:18:04,260 --> 00:18:05,430 under a name space 430 00:18:05,430 --> 00:18:07,740 that allows only the administrators group 431 00:18:07,740 --> 00:18:08,673 to create objects. 432 00:18:10,350 --> 00:18:11,850 The malware will try to create 433 00:18:11,850 --> 00:18:15,600 the exact same name spaces the EDR agent uses. 434 00:18:15,600 --> 00:18:17,760 To do that it needs to have the same name, 435 00:18:17,760 --> 00:18:19,050 which is easy, 436 00:18:19,050 --> 00:18:21,360 but also the same boundary descriptor. 437 00:18:21,360 --> 00:18:24,060 The malware can't create it 438 00:18:24,060 --> 00:18:26,790 because it is running as a low privilege process. 439 00:18:26,790 --> 00:18:28,740 So let's see what's happens. 440 00:18:28,740 --> 00:18:30,450 It will try to do it, 441 00:18:30,450 --> 00:18:33,150 but then it will fail and exit. 442 00:18:33,150 --> 00:18:35,430 Then the EDR agent starts. 443 00:18:35,430 --> 00:18:37,440 It starts as a privileged process, 444 00:18:37,440 --> 00:18:41,580 so it is able to create the exact name spaces it needs. 445 00:18:41,580 --> 00:18:45,630 And then it is the first process to create this mutex. 446 00:18:45,630 --> 00:18:48,420 So there will be our success 447 00:18:48,420 --> 00:18:50,520 and it will be able to protect the system. 448 00:18:52,380 --> 00:18:56,190 So basically namespaces protect named objects 449 00:18:56,190 --> 00:18:58,350 from unauthorized access 450 00:18:58,350 --> 00:19:01,170 and creating a private namespace enables applications 451 00:19:01,170 --> 00:19:04,710 and services to build a more secure environment. 452 00:19:04,710 --> 00:19:06,783 So let's see how we do that. 453 00:19:08,250 --> 00:19:11,583 The first step is calling create boundary descriptor. 454 00:19:13,260 --> 00:19:16,440 and then the security IDs will be added 455 00:19:16,440 --> 00:19:19,983 by calling add security ID to boundary descriptor. 456 00:19:22,920 --> 00:19:26,640 And the final step is calling create private namespace 457 00:19:26,640 --> 00:19:29,283 and send the boundary descriptor as a parameter. 458 00:19:31,380 --> 00:19:34,443 And this is exactly what the WER Service does. 459 00:19:35,340 --> 00:19:38,097 Let's look at the function, create private namespace. 460 00:19:38,970 --> 00:19:40,410 It creates a boundary descriptor, 461 00:19:40,410 --> 00:19:43,570 which is called WerSvcNameSpaceBoundary. 462 00:19:43,570 --> 00:19:45,560 Then it adds the security ID 463 00:19:45,560 --> 00:19:46,938 that represents the service 464 00:19:46,938 --> 00:19:48,722 to that boundary descriptor 465 00:19:48,722 --> 00:19:51,555 and creates the name space WerSvc. 466 00:19:52,458 --> 00:19:53,670 That means that events 467 00:19:53,670 --> 00:19:56,340 that are created under this name space 468 00:19:56,340 --> 00:20:01,340 were 100% created by WerSvc by no one else. 469 00:20:03,840 --> 00:20:06,570 Then the event is created 470 00:20:06,570 --> 00:20:09,180 and it is protected by two things. 471 00:20:09,180 --> 00:20:11,730 The first one is the name space, 472 00:20:11,730 --> 00:20:14,730 and the second one is the secure descriptor, 473 00:20:14,730 --> 00:20:16,350 which specifies the generic 474 00:20:16,350 --> 00:20:19,203 grid access only to the system user. 475 00:20:22,020 --> 00:20:25,170 So now we understand what is this event. 476 00:20:25,170 --> 00:20:27,750 So let's look at the validation checks that are 477 00:20:27,750 --> 00:20:29,940 performed by the service. 478 00:20:29,940 --> 00:20:32,040 The first one is comparing the idea of 479 00:20:32,040 --> 00:20:34,260 the process that send the request to the idea 480 00:20:34,260 --> 00:20:36,310 of the process that is being reported on. 481 00:20:37,590 --> 00:20:40,440 In our first example, we reported on ourselves, 482 00:20:40,440 --> 00:20:42,810 so those two values were the same. 483 00:20:42,810 --> 00:20:45,143 But now we're trying to report on LSASS. 484 00:20:45,990 --> 00:20:49,050 And the sender PID is set by the kernel, 485 00:20:49,050 --> 00:20:50,490 we have no control over that 486 00:20:50,490 --> 00:20:52,770 so those two values are different 487 00:20:52,770 --> 00:20:54,123 and this check fails. 488 00:20:55,290 --> 00:20:58,500 The second check is performed by the function, 489 00:20:58,500 --> 00:21:00,480 check if system connecting to port, 490 00:21:00,480 --> 00:21:02,550 the function we already talked about. 491 00:21:02,550 --> 00:21:05,493 And it basically checks the client security ID. 492 00:21:06,390 --> 00:21:10,650 Initially that check failed in our example 493 00:21:10,650 --> 00:21:12,210 but eventually we were able 494 00:21:12,210 --> 00:21:14,760 to pass this validation check. 495 00:21:14,760 --> 00:21:18,240 So that made the third one a bit irrelevant. 496 00:21:18,240 --> 00:21:20,520 And I won't go too into much details, 497 00:21:20,520 --> 00:21:24,030 but it compares the package name of the two processes 498 00:21:24,030 --> 00:21:27,480 and package names are related to Windows apps. 499 00:21:27,480 --> 00:21:30,393 So let's see how we pass the second validation check. 500 00:21:32,370 --> 00:21:34,080 Check if system connecting to ports, 501 00:21:34,080 --> 00:21:36,659 basically checks if the sender runs 502 00:21:36,659 --> 00:21:38,673 as NT Authority System. 503 00:21:39,660 --> 00:21:41,310 Initially this is what happened. 504 00:21:41,310 --> 00:21:45,450 Like I said, the thread started as NT Authority System 505 00:21:45,450 --> 00:21:47,670 then impersonated our user 506 00:21:47,670 --> 00:21:51,390 and the event failed opening the event failed. 507 00:21:51,390 --> 00:21:54,780 So all we needed to do is execute our tool 508 00:21:54,780 --> 00:21:56,283 as NT Authority System. 509 00:21:58,020 --> 00:22:00,060 Then after the impersonation, 510 00:22:00,060 --> 00:22:03,210 the thread stayed as NT Authority System 511 00:22:03,210 --> 00:22:05,733 and the event is opened. 512 00:22:07,590 --> 00:22:09,990 So to recap, this is that hack. 513 00:22:09,990 --> 00:22:12,240 We execute our tool system, 514 00:22:12,240 --> 00:22:15,150 it creates two undocumented stocks. 515 00:22:15,150 --> 00:22:17,970 The first one will be written into the file mapping, 516 00:22:17,970 --> 00:22:21,240 and the second one represents the LPC message. 517 00:22:21,240 --> 00:22:22,073 Then we signal the service, 518 00:22:22,073 --> 00:22:24,660 and it starts initializing. 519 00:22:24,660 --> 00:22:25,950 It creates the name space 520 00:22:25,950 --> 00:22:27,990 with the boundary descriptor, 521 00:22:27,990 --> 00:22:30,240 creates the event under the name space, 522 00:22:30,240 --> 00:22:31,833 and also the LPC port. 523 00:22:33,150 --> 00:22:34,410 Then we send a message 524 00:22:34,410 --> 00:22:36,933 and the service starts processing it. 525 00:22:38,400 --> 00:22:42,690 It compares the sender PID to the target PID that fails, 526 00:22:42,690 --> 00:22:44,220 and then it opens the event 527 00:22:44,220 --> 00:22:46,530 after the impersonation, that works. 528 00:22:46,530 --> 00:22:49,230 And the request is marked as valid 529 00:22:49,230 --> 00:22:51,720 and a dump is performed. 530 00:22:51,720 --> 00:22:53,553 So let's look at that. 531 00:22:55,380 --> 00:22:56,970 We'll launch our tool again, 532 00:22:56,970 --> 00:22:59,646 but this time no error code is specified. 533 00:22:59,646 --> 00:23:01,830 WerFault fault spawns as a child process 534 00:23:01,830 --> 00:23:05,620 and a memory dump of LSASS dot XC is produced. 535 00:23:05,620 --> 00:23:09,287 (crowd cheers and applauds) 536 00:23:13,950 --> 00:23:17,280 So now that we understand what is this attack, 537 00:23:17,280 --> 00:23:19,563 let's talk about detection and prevention. 538 00:23:21,480 --> 00:23:24,540 This attack leaves several artifacts on the system. 539 00:23:24,540 --> 00:23:25,923 Let's talk about each one. 540 00:23:27,540 --> 00:23:29,810 The first one is in the event log. 541 00:23:29,810 --> 00:23:33,780 The event ID an event ID with the idea 542 00:23:33,780 --> 00:23:37,290 of 1000 is generated under the application log. 543 00:23:37,290 --> 00:23:40,140 And it specifies that an exception occurred inside LSASS. 544 00:23:41,271 --> 00:23:44,396 But the most important thing is that our tool 545 00:23:44,396 --> 00:23:47,280 isn't mentioned anywhere in this event. 546 00:23:47,280 --> 00:23:50,040 This event can't be used to trace the attack 547 00:23:50,040 --> 00:23:52,023 back to us, back to our process. 548 00:23:53,790 --> 00:23:56,580 The second artifact is the dump file itself. 549 00:23:56,580 --> 00:23:59,520 It is created under the CrashDumps folder, 550 00:23:59,520 --> 00:24:02,790 and the existence of it is suspicious. 551 00:24:02,790 --> 00:24:05,580 But it is created by WerFault.exe 552 00:24:05,580 --> 00:24:07,710 and not our process. 553 00:24:07,710 --> 00:24:09,600 So the creation of the file 554 00:24:09,600 --> 00:24:12,243 can be traced directly back to us. 555 00:24:15,180 --> 00:24:16,950 Another log that is generated is 556 00:24:16,950 --> 00:24:19,440 under the WER Report Archive. 557 00:24:19,440 --> 00:24:21,390 It is a different type of log 558 00:24:21,390 --> 00:24:24,540 that specifies the details of the exception. 559 00:24:24,540 --> 00:24:27,480 And again, the most important point 560 00:24:27,480 --> 00:24:29,880 is that this process that sent the request 561 00:24:29,880 --> 00:24:31,653 isn't mentioned anywhere there. 562 00:24:33,840 --> 00:24:37,650 One thing that can't be used to detect this attack 563 00:24:37,650 --> 00:24:40,860 is the command line of WerFault.exe. 564 00:24:40,860 --> 00:24:42,690 It specifies the idea 565 00:24:42,690 --> 00:24:44,310 of the process that is being reported on 566 00:24:44,310 --> 00:24:47,460 and also the process that sent the request. 567 00:24:47,460 --> 00:24:50,040 So if the target process is LSASS 568 00:24:50,040 --> 00:24:52,020 and the source process isn't, 569 00:24:52,020 --> 00:24:54,273 it is a strong indication of this attack. 570 00:24:55,530 --> 00:24:59,520 But let's also talk about the advantages of this attack. 571 00:24:59,520 --> 00:25:01,350 WerFault is doing the dump, 572 00:25:01,350 --> 00:25:02,610 and this is great 573 00:25:02,610 --> 00:25:04,716 because it is a legitimate system process 574 00:25:04,716 --> 00:25:08,520 that exists on every version of Windows. 575 00:25:08,520 --> 00:25:13,520 The crash reports doesn't specify anything about our process 576 00:25:13,620 --> 00:25:18,620 and this tool can be compiled as both 32 or 64 bits. 577 00:25:18,930 --> 00:25:23,460 And the registry key we used the dump type is 578 00:25:23,460 --> 00:25:25,023 has legitimate usages. 579 00:25:26,970 --> 00:25:31,110 So these are the suggested actions for the defenders. 580 00:25:31,110 --> 00:25:33,720 Try to look for event ID 1000, 581 00:25:33,720 --> 00:25:36,600 which specifies an exception inside LSASS, 582 00:25:36,600 --> 00:25:40,590 but it isn't followed by a termination of LSASS. 583 00:25:40,590 --> 00:25:41,910 Also, like I said 584 00:25:41,910 --> 00:25:44,700 the command line of WerFaults can be used 585 00:25:44,700 --> 00:25:46,410 to detect this attack 586 00:25:46,410 --> 00:25:48,690 and also API monitoring. 587 00:25:48,690 --> 00:25:52,530 We can look for LPC messages that will be sent to Wer 588 00:25:52,530 --> 00:25:54,990 with the process ID of LSASS. 589 00:25:54,990 --> 00:25:59,733 And also depends on the network we can set LSASS as a PPL. 590 00:26:03,270 --> 00:26:06,210 Let's talk also about further research. 591 00:26:06,210 --> 00:26:09,720 And the first thing to do is look at other message types. 592 00:26:09,720 --> 00:26:14,720 The LPC message has the function that processes 593 00:26:15,510 --> 00:26:16,780 the LPC message 594 00:26:16,780 --> 00:26:18,930 yeah, has a lot of message types 595 00:26:18,930 --> 00:26:21,903 and the other message types might be exploited as well. 596 00:26:23,100 --> 00:26:25,620 And also we are using undocumented stocks, 597 00:26:25,620 --> 00:26:28,260 so that might change in the future. 598 00:26:28,260 --> 00:26:29,460 Specifically the stock 599 00:26:29,460 --> 00:26:31,800 that represents the LPC message. 600 00:26:31,800 --> 00:26:34,860 It has a variable that is called message size. 601 00:26:34,860 --> 00:26:38,310 And we already saw that in previous versions of Windows 602 00:26:38,310 --> 00:26:43,310 that's viable the value of this variable differentiates. 603 00:26:43,922 --> 00:26:46,353 So it might also be changed in the future. 604 00:26:48,240 --> 00:26:52,080 So these are the references for this research, 605 00:26:52,080 --> 00:26:54,392 and thank you very much. 606 00:26:54,392 --> 00:26:57,392 (audience applauds)