 Okay, how is everybody? I need your energy, right? Yeah! Okay, I drink some. Okay, so welcome to our talk, Defender Pretender, when Windows Defender updates become a security risk. We introduce ourselves first. My name is Tomer Bar, and I am the VP of Security Research at SafeBridge. Actually, we spoke 10 different talks at Black Hat USA, and this is our ninth in Defcon. And I've been around for the last 20 years. I presented in many global security conferences, and this year I was qualified to speak two talks at Black Hat and one at Defcon. Hey, guys. So, my name is Omer Latias. I'm a security researcher at SafeBridge. I have over six years of experience in cybersecurity, especially in low-level and vulnerability research. And I'm also a technology and science enthusiast. So, let's get it off. Okay. We will introduce our research motivation and goal, and then we'll describe in details Defender Pretender process and the vulnerability we discovered. We will demo different super interesting attack vectors, and we'll finish our talk with important takeaways before leaving time for Q&A. Let's begin. So, in this session, we are going to walk you all through the process of how we turn Defender to Defender Pretender. And our motivation originated from the flame malware used by probably state-sponsored threat malware and exploited the Windows update process using a sophisticated man-in-the-middle attack. Flame was able to hijack the Windows update mechanism by posing as a legitimate Microsoft update server, allowing it to deliver malicious updates and maintain persistence on the target system. Our goal was to achieve similar capabilities, but running without admin privileges, without possessing a Forge certificate, and with no prayer requirements of man-in-the-middle, and still achieve full takeover on Defender workflow. So, let's start to analyze the Defender update process and understand what happens locally during an update. So, Defender, check with the Microsoft update center for new updates. We found out that the updates are returned as a single executable. The file full name is pretty long. It's called Microsoft protection anti-malware front-end, so we will refer to it as MPOM from now on. And we downloaded this MPOM file, analyzed it, and found that it has a cab resource, and then we manually extracted the resource and got six files, two executable files, MP Engine and MP6 tab, and four files with unfamiliar VDM extension, at least for us. So, when we try to execute this MPOM file, we observed that it was executed the MP6 tab as a child process using the mark command line in red. After the execution, we saw that Defender was updated, so it seems like the tab's role is to initiate the update process. The VDM files are loaded to Defender's main process, as you can see here. MP Engine DLL was also used by the process, and this DLL exports Defender's core functionality. Let's investigate a little bit more about this VDM files. So, the VDM files are actually portable executable files, meaning application. However, they cannot be executed, as they have no code logic at all. So, we assume that there are special data files that contains the detection signatures. Furthermore, we observed that the two of them are labeled with the keyword base, and the other two are labeled with the keyword delta, with the main difference being their sizes. The base file are significantly larger than the delta files, and we speculate that this is due to incremental updating for efficiency reasons, because you probably don't want to send the entire database each time you have to have a small update, right? It's not efficient. And the base file has a major version of 391 and zero minor version, and the delta file has the same major version and 3508 has the minor version. And it's important, and I'm telling you that because the delta version represents the current version of Defender's security intelligence. So, it may indicate that the delta files are related to the signature data. But a quick check reveals that all six files are digitally signed by Microsoft, which probably indicates that the update process was designed against tempering. However, let's continue to explore furthermore before reaching a definitive answer to this speculation. So, to summarize the update process to the ones that come in right now, the MPAM file is fetched from the internet. And in point execution, it triggers an update. And the following three steps occur. MPAM extracts the VDM files, MP engine and MP6 tab from itself into the update payload folder located at the temporary direction, directory, sorry. And MPAM then executes the 6th tab in order to perform the update. And finally, 6th tab takes the VDM files and MP engine DLL and use them to update Windows Defender. So, easy, right until now. So, now that we have gained high-level knowledge about the update process, we can start to play around with the files involved. If we will be able to modify MP engine DLL to our own fake DLL, it will be a game over for Defender resulting in local privilege escalation, right? So, we modified a valid update payload that we have downloaded from the internet and replace only the original MP engine DLL as you can see with our fake DLL, even though the DLL was digitally signed by Microsoft, the original one. And then we executed this tab executable with the appropriate command line and, of course, this attempt failed. During a kernel debugging, we got this exception at the top that tells us that the DLL is not signed. This protection is implemented since Defender main process is a protected process, a PPL process which cannot load unsigned DLLs. So, in that point we thought, is this the end of our research lead? We decided not to give up and focus on the VDM files. What will happen if we update Defender using a modified older VDM file? So, we decided to modify only the file version, which is embedded inside the file. So, making Defender believe it's a newer version, but without modifying the data itself. Of course, this modification will turn the VDM to be unsigned, because it's embedded in the file, but we decided to give it a shot anyway. And for our surprise, the update attempt succeeded. We actually update an older version, pretended to be a newer version. And most importantly, using unsigned files with the low privileged user, so this was the first clue that something is fishy. But when we try to modify additional random bytes in this VDM data itself and not just the file version and execute a second update, we got an error. So, we understood it won't be that simple and we have to learn more about the update process. So let's summarize what we accomplished so far. We understood in high level, Windows Defender update process, and we have become familiar with the involved file, right? We attempted to modify MP Engine to use our own fake DLL, but we're unsuccessful in doing so. However, we did successfully modify an older update payload to appear as a new update payload by modifying the VDM files, but finally got an error when we updated using VDM file with modified data. So we left with the question, how does a low privileged user can replace files managed by Defender protected process? We began to analyze MP6 tab. After a bit of reversing, we understood that MP6 tab communicate with MSMP Engine, which is the main process of Defender via RPC, remote procedural calls. But at that point in time, we were unable to find the specific RPC interface which was used, and the challenge was even more difficult since RPC tools that we all use like RPCView could not display the RPC data due to involve protected process. So we did manual reverse engineering and revealed that the RPC GUID which belongs to MPSVC DLL and that the function number parameter was 42 corresponding to a function name server MP update Engine signature, which by its name indeed seems like the function we were looking for. After the RPC is done, the execution will continue from Defender main process on the right and will reach in it Engine contents function, which start the update process by calling the R signal function in our MP Engine DLL. So now we are ready for dynamic kernel debugging to understand the rest of the execution flow. And as you can see, the execution flow is pretty long, right? We will skip to the interesting part in the low database function, which is called for each VDM file. So now we know for sure that the VDM is indeed contains the update database. Let's analyze the database format. So we will be able to modify the data in much smarter way than we did before, like in random data modification. As we mentioned, the VDM file is Windows portable executable files with no code logic, but it also includes a resource section. And this resource section contains compressed data that start with RMDX magic bytes. And the signature in both the base and the Delta files are compressed with Zlib, but Zlib magic bytes are absent. So by simply adding these two bytes at the bottom and running this simple command, it can be decompressed. And we were very surprised to see that the signature are not even encrypted. So in a brief look over the base file, we could literally see where signatures begins and ends, and probably the actual unique strings defender searches in order to detect, for this example, the country around somewhere. But the Delta file format appears to be a little bit more complex. And we have decided to prioritize understanding it to a later time. So now we are going to focus on the base file. And the base file as we assume as the most of the signature logic, because it's larger. And it seems easier to understand its format. So let's see what we discovered. So each signature has a four byte signature header which contains signature type and size. The type is one byte long and the size is three byte long. And the signature data begins just right after the signature header. So simple structure. And instead of reversing each signature type, we search on Google and for some relevant information and found this comprehensive list of signature types. Each thread starts with a signature type 5C. A thread is a collection of signature. These signatures are simply unique strings or byte sequences which belongs to a malware family. You can see several strings from the country thread. And the collection of the signatures always ends up with a single thread and signature 5D type at the bottom. The base file is actually a sequence of threads. When one thread ends, the next thread starts and so on. So using this knowledge, we were able to extract more than two and a half million signature from the base file. We figure out most of the member of the signature. For example, the thread name, its category and severity of the thread. Now we can conduct an experiment in order to verify if we can modify it in a more smarter way than they did at the beginning of the research. So we extracted the strings from the VDM files, copied them to a Visual Studio environment and compiled a simple executable containing the strings. But as you can see, without any logic, as you can see in line 16, the main function is empty. And then we copy this executable to a virtual machine with Defender. And in a minute, immediately, it triggered Defender, even though there is no malicious code at all. And as expected, the thread alert name is the name of the thread we investigated, Conti, as you can see at the top. Then we modified just the thread name associated with the signature from Conti to a different name, recompressed the VDM file and tried to update Defender using this modified version. Unfortunately, this attempt was unsuccessful and resulted in unexplained error. We assume that the error is due to validation mechanism and Omer will speak about those validations. Okay, so we went back to the drawing board and reverse engineer the update process with the goal of identifying the point where the update failed and why it failed. So a quick reminder for each VDM file, load databases called and then checks the validity of the file and then calls to consume input compressed function. Consume input compressed function is a huge function that perform a lot of operations on the VDM files. Also, we suspected the function to be the function that returned the error code we saw in the logs. So we focused deeply on the internals of these two functions and specifically on consume input compressed function. We did it by dynamically debugging the update execution. So let's see what we got from debugging. The debugging led us to figure out two important structures that contained in each VDM file. The first one is the RMDX header which appears in the beginning of every VDM resource data. One of the important members of the RMDX header is the data offset which points to a second header called Zilibeter, which we can see marked in blue. The Zilibeter actually contains the Zilib compressed data of the VDM and also consists of two vars and the second and the second vars suspected to be the CRC of the compressed data. So we tried to calculate the CRC value of the compressed data, but we didn't get the expected value. So maybe this is not a CRC. So we tried to locate the point where this value is accessed and discover that it's compared to a variable calculated using an algorithm similar to a CRC calculation. So after searching on Google, we found out that this is a specific CRC algorithm called gemCRC which is calculated by one minus the CRC value. So we were confident that we could modify the VDM and fix the expected CRC value that appears in the headers and by doing so, the update would be validated successfully and we would be able to take down Defender. But the update was unsuccessful, even though we fixed the CRC value of the compressed data. Likely there are additional validation checks and we thought where do these validation occurs and what they validate. So let's find them out. The modification was simple. We just opened up the base file and tried to modify the signatures and after the modification, we wrapped up the base file and tried to do an update attempt. But it turned out to be quite more complicated than we thought. We completely ignored the delta file and we assumed that the error we got related to the relationship between the base file and the delta file. There are two pairs of VDMs. The first pair contained the antivirus definitions of Defender and the second pair actually contains the spyware definitions. Each of these pairs is identical in terms of the format of the file and the signatures. So all the findings and the conclusions we will show now apply to each of these VDM pairs. Okay. So as we mentioned earlier, we ignored the delta. But now it's time to focus on the purpose of the delta file. During an update, both the base and the delta files are involved. The merge takes the base file and the delta simply defines the changes to be made to this base file. The resulting output file will represent the updated version from the delta. And this update process is referred to as incremental. To modify base signatures, we need to supply a delta file that precisely patches the base file with the intended changes. But to do that, we need to understand the entire merge process internals and identify any other validations that we encountered. So now we will delve into the merge process. Oh, sorry. So we have talked about the VDM file format and specifically the base file format, which contains threats and their signatures. Now let's look into the delta format and how it combines with the base file to create new file with new signatures. So we went back to the decompressed delta file and we figured out that the delta is a signature base file too. We saw that the delta always contains two signatures. The second signature is blob signature type and we ignored the blob wrecking for signature as we assume all the essential data contained in the blob signature. So right after the signature error, we have two numbers which we were not sure about their purpose. So we will call them unknown for now and we will come back to them later on. The rest of the data right after these numbers is actually the actions which define the actions done by the merge algorithm. How do they define the actions? Now we will answer this question. So we spotted the point where defender parse the actions. And this block of code shows where actually the action parse start. And we reverse all the merge process and figured out how the merge works. So let's delve into the internals. So we identify two action types. Copy from delta and copy from base. Copy from delta used to copy size bytes from the delta file into the merge file. And copy from base used to copy size bytes from an offset within the base file into the merge file. Let's see exactly the format of each of these signatures. So to parse the actions, we first need to read two bytes representing the action error. The first bit within the action error indicates the action type. Zero four copy from delta and one four copy from base. And the rest of the action error is dependent on the action type. So first let's take a look at copy from delta action. Here we have an action example. And the first thing to do is to read the first two bytes and check the MSB to identify which type of action is it. The MSB is zero means this action is actually copied from delta. Then it means that the next 15 bits represented the size variable which tells us how many bytes to read. So the size variable is set to one in this case. So we read one byte right after the action error. So in this case, we will read five C and place it into the new merge file. Okay, now that we understand how to parse copy from delta action, let's move on to copy from base action. So when we look at copy from base action, we can see that the MSB is on. But in this case, after reverse engineer of consuming put compressed function, we found out that in this case, the size variable calculated in the following way. Firstly, we take the two bytes and turn off the MSB by and bitwise with seven FFF. And then add to this result six which result the size variable. We now know how many bytes to read. But the question is where we will read them from. So copy from base action type consists also the offset variable. The next the word right after the action error indicates the offset within the base file we should read the bytes from. So in this example, the size is equal to 8,005. And we should read them from the offset one of the base file. And eventually place them into the new merge file. So to summarize the delta file, so to summarize the delta file contains compressed data. And by decompressing this data, we can extract the blob signature. The blob contains actions. And the actions tells how to build the new updated file, depending on the current version of the base file. And all these occurs in memory. So following our knowledge, we developed a script that do that merge between the base file and the delta file. We ran our code and got a merge stream that actually seems like a base with signatures, but with some modifications. And we can see a diff between base signatures to emerge signatures. The bytes that marked in yellow are the modified bytes. And the size of the data got bigger. But probably the merge process added some new signatures. And ear things are starting to reveal a clear image of what happening. As we said before, we will talk about the unknown numbers we mentioned before. So we started to investigate the merge properties like the size of the merge and the CRC of the merge. And we looked up for a correlation to the unknown numbers. And I got it. The first number represent the size of the merge data. And the second number is actually the CRC of the merge data. These two numbers are the expected values that defenders compares with. And the numbers is actually one more layer of validations. So I want to recap the three validations we discovered. The first validation simply checks if the Zlib compressed data isn't changed. And how does defender checks this? By comparing the expected CRC value within the Zlib data either to the calculated CRC of the Zlib data. The next validation are the ones we just mentioned. Merge size validation ensures the size of the merge data. And merge CRC validation validates the CRC of the merge data. These checks confirm the success of the merge algorithm. So we wondered if now we have all the knowledge we need in order to fake an update. So we try to change the delta actions in such a way that the merge will result with a difference. And it worked. We managed to update defender with a fake unsigned database using unprivileged user. It's crazy. Let's see what we can do with this capability. We will explain three attack vectors. We have developed a fully automatic tool called WD pretender, which stands for Windows Defender pretender. This tool supports all the attack vectors that we are going to present. And we will share the GitHub link at the end of the talk. So as we explained earlier, the signatures of defender resulted from merging the delta file and the base file. The database files of defender are composed of threads. And each thread has its name. And we can confirm from the name the purpose of the thread, right? Now, what will happen if we will delete all the threads that contain the keyword lasagna, for example, in their names? Let's see. We will show our deletion of thread resulting with bypass and we successfully execute lasagna tool. Let's see. So now we are seeing that we are unprivileged user. And we will try to download lasagna tool. And it immediately triggered defender. And defender will delete this tool. Now we will run WD pretender and delete all the threads that contain the lasagna name in the threads name. The tool will explore the VDM files. And we will run an update attempt with this tab. And we will see in a sec that the update executed successfully. And now we will try to download lasagna tool again. Let's see what we get. Perfect. The tool downloaded. And we will execute successfully lasagna. Okay. Now, Tommy will present the next demos. Okay. So one of the signature types seems very, very interesting. The name that Microsoft named it is friendly files signature. And with Ash algorithm like 256, as you can see on the left, on red. So we wonder what do Microsoft means by friendly files. So passing all the friendly file signatures from the VDM files revealed us a very, very long list of sorted list of hashes. The Ash marked in green on the right belongs to Oracle virtual box runtime library. And the others belongs to other files. And we assume that this signature is probably an allow list implementation. Probably to reduce false positives caused by example, this Oracle file. And what will happen if we replace the Ash value of Oracle file with the Mimicats known Ash value. We didn't change the Mimicats from the internet. Will it be allowed to run? Can we create a friendly Mimicats file? Let's see a demo. Okay. So we'll try to download Mimicats. It is detected as Mimicats on the right. So Defender is working. Now we will execute on the left. Again, Windows Pretender Defender. Defender Pretender, sorry. And with the Ash of Mimicats, the known Ash, then we will update and you will see on the right that the update was successfully from unprivileged user unsigned files. And you can see you can also see that the logs are saying the same that the update was successful. Now we will try to download Mimicats from the same place. And let's see if it runs. Yeah, it runs. Let's see if we can extract all credentials from the memory of Elsas. Yeah. Right. Thank you. And now for our final demo, we saved the best for us. This is going to be very, very cool. Trust me. We are going to force Defender to delete all the P files in the PC by modifying existing emotes signature to include the DOS mod stop string, which appears in all of the portable executable as a new malicious signature. And when Defender will find this string, this program cannot be run in DOS mode since the 80s, right? In OS files, it will automatically say I'm going to delete you and causing permanent denial of service. So we run our tool, generated database. We are going to copy it to a machine, replace it, and we'll do an update after that. That's the user that is an unprivileged user. And we'll run the update. And on the left, you will see the update succeed. Okay. Now we'll wait like a few seconds. It's not edited at all. And Defender started to say something about a lot of files detecting as emotes. And it's keep going, it's keep going. If I had sound right now, you will see like a lot of concerts, you know? And Defender said, what's going on? Restart the computer. But we are not going to do it. We are going to scan the driver folder under system 32. Thank you. Thank you. And let's see, let's see what happens. And we'll do, we'll show you that all the drivers and DLL files and processes and registries and everything. And of course we can do it also in user files that contain a specific world like Defcon. Any file that contains Defcon, we can delete it and so on. And trust me, Windows cannot load without the drivers. It won't work. So we tried, we tried. We have a secondary start attempt, but believe me, it won't work. So it's a permanent denial of service. And this demo was recorded on an older version of Defender. It was version 321. And the newest version at the time of the check 381 implements few additional checks. For example, we had to remove all the signature type trusted publisher to make Defender delete behind drivers and OS executables, but it works. Let's speak a little bit about future work. And it's very interesting. We found out that the signature database file also includes 30,000 Lua scripts. Microsoft used a little bit of modified Lua header for them, but we were able to overcome the modification and to decompile and extract the source code of 30,000 Lua scripts that control all of the remediation process of Defender. So for example, a Lua rule to detect suspicious files masquerading as legit Windows files. The rules simply checks if a file has the same name of OS executable, but not in the legit OS path. What will happen if we change this rule code to our own code? And we try to use Lua libraries, but failed since Microsoft probably limits the usage of Lua libraries. But we still think that we might be possible to achieve LPE local privilege escalation using Microsoft remediation library which we saw used in some of the other Lua scripts, but we had to leave it for future work because lack of time, but we encourage you to do it and please update us if you can do it. We will try to after Defcon. So a little bit about takeaways. Of course, trust no one, we are Defcon, right? Even the most reliable security controls might be used as a loophole by adversaries and the architecture and work process should check and verify in continuous security validation process. Secondly, using digitally signed files does not always necessarily mean totally secure. Security vendors should always verify in any step of the process that the trust was not broken. And finally, signature update process of security control is probably a new attack vector and we believe additional research is very important. We reported to Microsoft which released a patch and assigned DCVAD. Please make sure that you are using the version of malware protection platform or above. Keep your cameras. This is the Windows Defender pretended GitHub QR code and link. I will wait a few seconds for those of you would like to follow it. And this past research helped us a lot and we built a research based on their initial findings. So thank you. And thank you all. Thank you all for joining us.