This is Patrick Wordle. And his talk is you're muted. I'll scratch that. Rooted. Aloha and welcome to my talk on exploiting Zoom. My name is Patrick. I am the founder of the Objective C Foundation. I also write free open source Mac security tools, write some books on Mac malware, and organize the Objective by the C Mac Security Conference. So today we're going to learn about local privilege escalation vulnerabilities impacting Zoom's Mac OS clients. Bugs that allowed a local attacker or an unprivileged piece of malware the ability to gain root. So we'll start the talk highlighting some previous but relevant research and also talk about some of the things that we're going to be talking about, an interesting new feature that was introduced recently in Zoom. We'll then discuss a crypto bug, a downgrade attack, and then end the talk talking about how Zoom fixed these vulnerabilities. Now, besides learning about these bugs, I also hope that this talk highlights the techniques and approaches I use to find vulnerabilities on Mac OS that maybe you can apply to your own research as well. So let's start the talk by looking at some relevant background information, some previous research, and then we'll talk about these research as well as highlighting a new feature that was recently added to Zoom, a feature that is central to all the new bugs you'll be learning about today. So if you are at DEF CON 25 in 2017, you might have seen in my talk on installers. The TLDR of that talk was basically as follows. Installers often run as root, but with these elevated privileges perform unsafe actions. It allows a local attacker or unprivileged malware the opportunity to surreptitiously subvert the install process to gain root access. So, for example, as we can see on the slide, an installer will authenticate with the user and then maybe drop a file to a temporary location or some other world writable location. It will then execute sometime thereafter this file. So obviously there's a window where a local attacker or unprivileged malware could go in and subvert that file because it's world writable, add some malicious commands, and then when the installer comes to complete the install, it will execute those additional commands, giving the attacker root. More recently, in 2020, kind of the beginning of the pandemic when Zoom was really blowing up in terms of popularity, I dug around in Zoom. And the motivation for that and also the other bugs we're talking today is I'm a user of Mac. Sorry, of Zoom. And, you know, if it's running on my system, I want to make sure that it's reasonable. It's reasonably safe and not, you know, opening up my computer to a large amount of attacks. So I was digging around in its installer code and I found exactly the type of flaw that I talked about at my DEF CON presentation. So we can see on the slide I ran a process monitor to see exactly what the Zoom installer was doing behind the scenes. And we can see that it's executing a script called run with root. If we look at the UUID, the UID, we can see it's zero, which means it's actually, yes, executing as root. However, if we look at the permissions of this file, we can see it's world writable. It's owned by the user, even though it's being executed by root. So, you know, a local attacker could very easily modify this file and then when the installer comes along and runs it with root privileges, whatever the attacker has added will be executed, giving the attacker the ability to elevate their privileges to root. Moving on, end of last year, this is where we're kind of transitioning to the new research, I noticed a new feature in Zoom. Unsurprisingly, when you either insert a new feature in the installer or install Zoom or uninstall Zoom, it will prompt you for a password, as we can see on the slide. This makes sense as the installer and conversely the uninstaller need to perform privilege actions. However, there's a new feature I noticed, an auto update, which is enabled by default. And it appeared to be able to install new updates without requiring any user interaction. No password, no need to authenticate. Now, this is obviously neat from a usability point of view, but it's a little confusing. But from a security point of view, this really piqued my interest. I was like, how is this working? What's going on? So let's dig into this a little more because we need to gain a fundamental understanding of how this new feature works in order to understand the bugs we will talk about shortly thereafter. So, again, if we fire up a process monitor, we can watch what's going on behind the scenes. I like to start with a file monitor, process monitor, before jumping into disassembly or debugging. Because oftentimes you can get a very good insight into what is going on and actually having to do a lot of work. So we can see that the Zoom application executes an updater application called ZoomAutoUpdater.app. And I've highlighted two things about it. We can see the path to the application and also the fact that it contains or rather takes a myriad of command line options. And one of these options is the path to the update package containing the new code. So now let's do some disassembly. If we disassemble the updater app, we're going to have a map. We can see it making an XPC connection to a mock service named USZoom.ZoomDaemon. This is just kind of like an IPC mechanism, one process connecting to another. So that was interesting. It's like, what's going on here? So I did a little more research and I found this maps to a privileged Zoom daemon that runs with root privileges. If we look at the daemon's property list, we can see, as is shown on the slide, the path to the binary of this daemon. And it exists or lives in the protected privileged helper tool directory. So let's dig a little deeper into this binary. Again, this appeared to be a new binary and it's running as root. So from a security point of view, always good to audit those. So the first thing I did, I used a tool called class dump which allows you to dump classes and methods implemented in this privileged Zoom daemon. Here's a snippet from that output and it includes an XPC protocol class and its method. And one of the methods that stood out to me was something called install new package. And as we'll see on the next slide, this is what was invoked by the Zoom clients to perform a privileged install without the need for a password. So if we step back to the updater application, looking more at its disassembly, we can see it connecting to the privileged Zoom daemon and then invoking that aforementioned install new package method. Really neat feature of Objective C is privilege processes can actually invoke other methods in a remote process. So that's exactly what's going on here. So once the updater application calls into the daemon to install a new package, the install is completed when the daemon actually executes Mac OS's built-in installer binary along with the update package. And as this Zoom daemon is running with elevated privileges, right, it's running as root, the installer that it spawns also runs with root. So this is really neat. This is why the user does not have to type or reenter their password when an auto update or a new install is performed. So now we know how updates can be installed without the need for a user's password. Now, this privileged daemon, as I mentioned, was new and kind of a new attack surface. So as a Zoom user, my first question was, is this secure? Or is this opening up my system to new vulnerabilities? And, well, the good news was, at first glance, the answer appeared to be yes. And Zoom was doing two important things to ensure, or at least try to ensure, the security of this privileged daemon. So first, they implement some code, and we'll look at this on the next slide, to only allow privileged and authenticated Zoom clients to talk to the daemon. This is really good. You don't want random binaries connecting to your privileged daemon and invoking its method. Secondly, it also appeared that Zoom was validating the cryptographic signatures of the update package. Again, this is a great idea. You don't want the Zoom updater running arbitrary packages. Again, it's rude. So let's take a closer look at both of these. First up, in the privileged Zoom daemon, there is a method called isValidConnection, which is invoked automatically any time a client attempts to connect to the daemon and then execute its privileged methods. So as we can see on the slide, the Zoom daemon will validate the cryptographic signature of the client that is trying to connect to it and only allow that connection if it has been signed by Zoom proper. So this code looks solid. This all looks really great. The second security check, the Zoom daemon also checks, as I mentioned, the signature of the package that it's about to install, the auto-update package. And it does this in a method called CheckPkgPackageAuthority. And what we can see if we look at the disassembly is that it actually executes a built-in command line user. This is a utility from Mac OS called PackageUtil with the check signature flag. And then it grabs the output from this, looks for the certificate authority chain to make sure that the package that it's about to install is installed by Zoom proper. So far so good, right? Well, unfortunately not. So we just showed that the Zoom daemon checks the signature of any installer update package in an attempt to ensure that only Zoom packages are executed. As I mentioned, obviously this is a good idea. But as is the case almost always, the security or the insecurity of a good idea comes down to the implementation. So we noted that Zoom executes Mac OS PKG utility with a check signature flag. This will check that the package is validly signed and then also extract the certificate chain. We can see this on the slide. For example, if you execute the PKG utility yourself and give it a package, you can kind of see the output, right? So we see things like the certificate chain. Using the PKG utility is fine, right? That code is solid. But we need to take a closer look at how Zoom then ingests and processes the output from this utility. So on the slide, we have the disassembly from the daemon's check PKG authority method. And we can see that after they execute the PKG utility, they open a pipe and read all its input, rather all its output from standard out, and then look for the strings in the certificate authority chain that match Zoom. Now, the rather hilarious flaw, the issue is that Zoom looks for the certificate strings in the entire output from PKG utility. And guess what else is included in the output from the PKG utility? The name of the package. Such fail. So what we can do is we can just rename any package, even malicious ones, Zoom Video Communications, Inc., Developer ID, Certificate Authority, Apple Root, CA, dot, PKG. And bypass the verification. So we can see on the slide, again, this is because that the name is first printed out by the PKG utility, meaning that the strings Zoom is looking for, because, again, they're looking for these strings in the entire output from PKG utility, will be found. We can confirm this by popping into a debugger. Specifically, we debug the check PKG authority method in the daemon. So on the slide, note that the package we're asking for, asking Zoom to install, is named in that malicious manner. Essentially, you put the strings it's looking for in the certificate chain in the name of the package. And then we can see the verification method at the bottom of the slide is returning 1, or true, meaning it thinks that the package has been signed by Zoom, even though, obviously, it has not. Now, around the time I found this bug, I was really stoked. But that same week, Zoom pushed out an unrelated security update, which actually meant that I had to find another bug for a full exploit chain. But it turns out that wasn't a problem. So Zoom version 5.9 was released with security enhancements. And one of these enhancements impacted the exploitation of this package rename check I just talked about. Though Zoom didn't fix the buggy package validation, right, they still executed the PKG utility, read all the output, looked for the strings. Another part of their security enhancement logic meant that they now renamed the package before doing the verification. So, unfortunately, that means when they rename the package, if we have a package with the certificate authorities in the name, that doesn't matter anymore because Zoom is going to rename the package first, essentially wiping out those strings. Now, I know that the check is still done via the PKG utility, so they're still looking for those strings. So it did appear that there's perhaps other ways to still exploit that. Perhaps you could get a certificate that has that. It had all those strings in one name or something. But now it was definitely harder. So I was kind of pondering this in the shower, as one does, and I had this, like, shower thought. And I was like, wait a minute. So, yeah, it sucks that Zoom pushed out this update, but can I ask Zoom just to install an older version of itself, one that doesn't have these additional security checks? So I went back to the installer and I looked at its update logic in the daemon, and we can see that there was no change. So I would check on the version that they are installing. So this means it will gladly and naively install any version of Zoom, even older buggy ones, as long as they are still signed by Zoom. And they all still are. So armed with these bugs, now let's talk about exploiting Zoom from Zoom to root. First, though, we kind of have an issue that I've ignored or glossed over so far. So recall that Zoom, the privileged Zoom daemon, only allows validly signed Zoom clients to talk to this. So does this mean that we can't trigger the bug at any time, right? Do we have to wait until there's a legitimate install that comes down for Zoom and then, you know, hopefully pop in at the right time? That would suck, right? Well, while we were reversing the auto update process, we saw that the update request to the update daemon was triggered by a standalone application, the Zoom auto update application. And if we reverse engineer that, we see that the updater application takes a myriad of arguments, including, as I mentioned before, the path to the install package. Now, as the Zoom auto update application is obviously signed by Zoom, it is a trusted client. So that means we can trigger an update any time by just manually executing the Zoom auto update application ourself. All right. So now I'm going to do a brief demo. It's always a good idea to do live demos. We're just going to show the fact that we can trigger an install of Zoom at any time. So this isn't an exploit. I'm basically just going to tell the privileged daemon, hey, I have an update for you, and I'm going to give it a real version of Zoom. So the first thing I want to show you on the slide, we've run the PKG utility, and the package I'm going to update is signed by Zoom. So execute this. This is obviously going to work. I'm just telling the daemon, oh, sorry, we lost the monitors. Thank you. Maybe if I turn off mirroring. Okay. Let's try this again. Okay. So now we have the, let me make this a little bigger. We can see, again, we run the PKG utility on the package I'm going to tell Zoom to upgrade to. Again, this is a legitimate version of Zoom. I'm not doing any exploit at this point. I'm basically running the auto update application. We can see here's the prompt from Zoom, and this is going to just install a version of Zoom. Hooray. So, again, this just shows that at any time we can tell the updater daemon that, hey, just to let you know, we can trigger an update. Okay. Let's continue this. Okay. So now what we want to do is we want to exploit to gain root. So we can do this in two steps. The first thing we do is we execute the auto update application that we just demoed, and we give it an older version of Zoom. This is a validly signed version of Zoom, but it doesn't have the additional security enhancements that break the name trick. Once this has completed, we then execute the update application again, this time with our malicious package that we've renamed so that it finds the certificate authority strings in the package name. End result, we'll have a root shell. So here is a prerecorded demo. We can see we're going to first execute the update installer, just like we did in the other demo. This is going to install an old version of Zoom. Once this is done, we're just going to execute the auto update application again. This time, though, you'll see the name of the package has this long name with all the certificate authority strings that Zoom is looking for. Right there. And then this is going to be executed and pops this root shell. So hooray. Wee. But wait. We can make this better. In the video, the demo, we saw there was a big pop-up saying Zoom is updating. If you're an attacker, that's not good news. So I said, okay, how can we make this better? So I continue to reverse engineer the auto update application, and as I mentioned, it takes a myriad of arguments. Two of these arguments control the UI, the user interface, of the upgrade. Specifically, the fifth and sixth arguments. If you set those to zero or false, this tells the updater to perform with no alerts silently. So this makes our exploit now 100% invisible. Hooray. So now let's talk about how Zoom fixed these bugs. I'm always interested in what they did. So first off, they assigned a CVE for the downgrade attack. This was fixed in version 5.9.6, which was released in April of this year. Took about four months to fix that. And they gave out a nice bug bounty for that. This is the kind of security details from that. So let's dive now into the disassembly to see how they patch this. So this patch exists in the privileged Zoom daemon that's running with root privileges. And now what we can see is they're checking the version to make sure that whatever version is about to be installed is in fact an equal or an upgrade. So it's not a downgrade. So they do this by unzipping the package, extracting the version number, and then doing a comparison. The very bottom of the slide, we can see where they do the comparison. And again, this ensures that the update version is indeed either equal to or greater than the currently installed version. So now if we try to perform the downgrade attack, as we can see on the slide, this is going to fail. It's basically going to say, GTFO, this is an old version. I'm not going to use it. I'm not going to install this anymore. So that's great. The package validation vulnerability took a little longer to fix, about seven months. But again, they paid out a nice bug bounty for that. This was fixed in July 2022. And if we look at how they do this, we can figure out the new implementation to see how they securely patch and check the verification of packages. So if we use the O tool utility to dump the dependencies, and then the NM tool to look at the new imports and methods, we can see that they're now leveraging some new cryptographic APIs. So instead of executing the PKG utility, they're now using various cryptographic APIs to check the code signing certificates of the package securely. So again, this is a sufficient fix. And we can see that when we execute now an unsigned package or a package that has been signed by anybody but Zoom, this will fail. A better option, in my opinion, would be do exactly what PKG utility does. So what I did is I reversed PKG utility and found the private framework it utilizes. And in that framework are some very powerful APIs that can check the digital certificate of any PKG for you. And so I released some code. This is actually how I verify packages in my tool. I mentioned it's, you know, a private framework. But other than that, that's exactly how Apple goes about doing it. So I figured, hey, why not be inspired by them? So this is open source. If you pop on GitHub, you can check out how to securely validate packages using the same technique that Apple's PKG utility does. So that was my DEF CON talk up to about a week ago. And I was like, okay, it's a solid talk, some neat bugs, everything's fixed. We talked about some reverse engineering. But I thought, you know, this is DEF CON. DEF CON demands great talks. So I wanted to dig a little bit more. And again, I was in the shower pondering life. No, I'm just kidding. I was pondering Zoom. And I was like, you know, there's still something that isn't quite sitting right with me. So now let's talk about another flaw that currently exists even in the latest version of Zoom. So this is currently a zero-day vulnerability. Recall that the update package is moved and renamed and then validated. And again, this was part of a security enhancement that broke my initial bug indirectly. So if we look at this a little closer, we can see the name of the package is always going to be Zoom TMP.PKG. This is what Zoom renames it to. If we look in a debugger, we can see the copy operation is performing. And what they're doing is they're copying it into a directory that is owned by Root, specifically the library application support Zoom.US. Once the package is copied into this directory, it is then verified correctly now using the more secure APIs. And if and only if it passes the verification, it's executed. So again, if we look at this, it's like, okay, this is great. Directory is owned by Root. This means users can't create new files, can't delete files. They're using the new APIs. Everything's great. But, and this is a big but, there's a very nuanced issue here. So I mentioned the directory is owned by Root. The problem is that when Zoom copies in the update package, they don't change the permissions. So even though it exists in a Root-owned directory, the update package is still world writable. This means any local attacker, unprivileged malware, can surreptitiously modify the update package. This is a classic time to check, time to use, erase condition. Basically what happens, as I mentioned, is Zoom, the privileged daemon, comes along and copies, renames the application into the Root directory. It verifies the signature, unzips it, and then installs it as Root. So again, if we're correctly timed, is there an opportunity for us to surreptitiously pop in and modify this after the verification but before the application is installed? It's a great question. The good news is this race window is rather large. And this is because that Zoom performs many other very expensive and slow operations after they have verified the package but before they install it. Specifically, they unzip the package as part of the version check. And they do that by spawning additional processes, which is a very expensive and slow operation. So basically we have a very large window. So here's the exploit. It's about ten lines of code. As I mentioned, it works on the latest version of Zoom. So if you're running Zoom, lucky you. And we can see it basically does three things. We execute the Zoom auto update application. Again, this allows us to trigger an update. We have to give it a validly signed package from Zoom. So we just grab the latest version. We don't actually care what it's installing. We just need to trigger any installation logic. And again, we can do this because the auto update utility is allowed to talk to the Zoom client. And the package we're telling Zoom to install is initially a valid Zoom client. We then wait until the copy of the package comes along. Wait an additional millisecond or two. And again, because Zoom forgot to update permissions of this package, we can now, with no privileges, modify that package. And as long as you do it before the installer is invoked, when the installer comes along with root privileges, it will then install our package. All right. I'm going to say a prayer to the demo gods because we're going to try to do a live demo of a race condition. Yeesh. Okay. Here we go. So what we're going to do, and we'll look at the exploit code shortly, is we're going to perform those three steps. And this is obviously going to work. So first we see the installation coming along. Uh-oh. I totally jinxed myself. Wait for it. Wait for it. I didn't actually see a prayer. So maybe that was the problem. Sometimes it takes a while. All right. Let's try this again. So let me just maybe see if the installer is running. No. Let's see if we can come over here and do the ALO update. Might need to reinstall Zoom. I did make a video of this, so if this fails, we'll just look at that. So I'm just going to reinstall Zoom, kind of get a base condition. Come on. Okay. Let me look one more thing. Installer. Okay. Maybe we'll try this again at the end. Okay. Well, clearly I broke something. Maybe Zoom's asking me to install it. So let me try one more thing, and if not, we will move on. Okay. Lots of Zoom things running. Let me just kill you this quickly. Appreciate your patience. Maybe I, you know, tried the demo too many times. Kill-9. Is that all of them? Oh, wow. Three more. I guess I should have just done a kill-all. Okay. All right. One more time for good measure. Let's come over here, tell Zoom to update itself just to get a clean version. Okay. Say another prayer. Come back to the exploit. Run it. Okay. Hooray. That worked. Mahalo for your patience. All right. So now we have a nice exploit. But again, I mentioned that, or as you saw, there was a bunch of pop-up windows, and so if you're trying to exploit this locally and there's a user on the system, it's a dead giveaway. So let's see if we can improve this. So let's close this root terminal, pop in here, pop into Vim, and modify the exploit. And I mentioned that the auto-update application utility takes a large number of command line arguments, and one of those controls the user interface. So what we're going to do is we're just going to update the exploit and say, you know, don't show a user interface. So that one's going to be command argument number six. So I'm going to change that to zero. Ooh, how do you exit Vim? Kidding. And now we're going to run the exploit again. And hooray. Now we have a root shell. But with no other alerts. Now since everything's working, I mentioned this is a race condition, so one of the parameters that the exploit takes is how long to wait. I've hard-coded this for this, or I know the value for my particular system. Obviously if you're exploiting this in the wild, you're going to have to do a little bit of playing around. For example, if you do zero, we're going to see that's way too fast. Let me go back and turn the UI on again. We're popping root shells all over. So since it's a race condition, you have to kind of get the timing correct. So if I come back to here, anything other than zero, and we tell it to do exploit zero, this should probably fail, right? It says fails with error code 007. If you look at what this error code means, it means that verification failed. So remember the first thing it does is it copies it and verifies it. So if we jump in too fast and replace the package, the verification is going to fail. It's going to see that it's not signed by Zoom. So we have to wait a little bit. Conversely, if we wait too long, like two seconds or something, the installation is going to install the legitimate version of Zoom. And so we've basically missed our opportunity window, right? So Zoom in this case grabbed the package, installed it, we replaced it, but it already had gone too long. So you kind of do some playing around, but again, as I mentioned, you can do this silently by changing that flag. So you could execute this as many times as you want on a live system or a target system, changing that until you, you know, get the right time and win the race. So again, 0.1 seems to work pretty well. And we get, you know, lots of root shells. So, okay. That was stressful. Life lesson. Don't give up. All right. So it's a very nuanced bug. It's a very subtle bug. It's a great bug. But it also has a trivial fix. So again, recall the fact of the bug is Zoom simply forgot to change the permissions when they copied the upgrade package into the root-owned directory. All they have to do to fix this is to update the permissions once they've copied this in before they verify this. Again, the directory they copy it into is owned by root. So if they change the permissions on the package to the root, that would thwart any local attacker because the local attacker then would not be able to modify either anything in that directory or the PKG itself. So there's a single line, a single API call you can call in Objective-C. You could also use C, do this in Swift, and simply change the permissions on the file. So I've gone ahead and done this manually and we basically changed the permissions of that Zoom TMP PKG, the update package, and we set it to be the owner of the directory, and on this, our exploit will now fail because when it goes to try to modify the package, it doesn't have the permission because, again, we're running with lower privileges, we're trying to get root. So hopefully Zoom will push out a fix for this. Again, pretty simple fix. All right, so let's end with some conclusions, some takeaways. First and foremost, be very, very careful choosing usability over security. And this applies not just to Zoom but to everyone. If I have a critique of Zoom it's that they continually choose usability over security. And, you know, who can blame them? That's what we, that's what users want, right? If that wasn't the case, maybe this wouldn't be the reality. In this case, if Zoom had simply asked the user for their password and then used the installer every time an update came along, I wouldn't be here. None of these bugs would have existed. Again, that's a little more problematic for the user. I mean, it inconvenienced them slightly. So again, from purely a usability point of view, I understand what Zoom did. But from a security point of view, they opened up this huge attack surface, which in retrospect, I really don't think was a good idea. Second, the fact that installers have problems is not a new, it's not a new thing, right? I talked about this at DEF CON. Zoom had already 3, 4, 5, 6 other bugs in their installer code. This was all really talked about in my and other people's talk. So watch DEF CON talks. And then finally, and this is another kind of critique I have about Zoom, and also applies to other software, where there are bugs, several bugs, there's likely to be more. I looked at the installer, every time I look at the installer, there's new bugs. So this is a little, again, disappointing, but from a security research point of view, if you want to find a lot of bugs, find an area that is new or has other vulnerabilities, and you will likely find more. I also briefly want to mention, if you're interested, if you enjoyed this talk, you're interested in reverse engineering, debugging, Mac analysis, I've written a free book on Mac malware analysis that covers a lot of the topics. You can grab a digital copy for free. It's also sold by NoStarchPress, so check that out. I also want to briefly thank the companies that support the Objective C Foundation, as I mentioned, that's the foundation I founded and work for. I also want to thank, obviously, the amazing DEF CON conference. It's incredible to be back at, like, full energy. I'm sure you're all stoked as well. And also I want to thank all of you for attending my talk. So I think we have a few minutes for questions and answers. So if there's any questions, let me know. I'll also be here after the talk so we can talk more. Yes, in the front. Yes. Where is it? No, no, no. Oh, man. Okay, let me do this the fast way. I think it's here. Okay, yes. Take a picture. Again, pretty straightforward. We basically just wait for that package to be we trigger an update request, wait for the package, and then replace it. So, again, this is not some incredibly sophisticated exploit. It's a pretty standard race condition that, again, is pretty winnable. Yeah, another question. Great question. So the question was, what are my tools for reverse engineering? I wrote some of my own tools. The file and process monitors, if you go to objective-c.org, you can grab those. Those are free, open source. For reverse engineering, I use the Hopper disassembler. It's about 99 bucks, so I think it's good. It's also very Mac OS specific and the developer is very responsive to bug requests. So it's just my tool of choice. Ghidra, IDA would probably work as well. And then for debugging, I use LLDB, which is Mac OS's Apple's built-in debugger. Yep. The question was, have I tried this exploit on any other apps? I have not. Also, this one is obviously specific to Mac OS. That having been said, the downgrade attack also impacted Windows. This, again, is something of a little bit of a critique of Zoom as well. I didn't even think to check Windows. I just reported, hey, your Mac client is vulnerable to a downgrade attack. And then, like, four months later, someone from Google Project Zero was like, the Windows version is vulnerable to a downgrade attack. And I was like, can I get that money? Not really, but, you know, the thought was, you know, if I reported this bug to Zoom, you know, you would have thought it would be like, okay, downgrade attack on the Mac client, maybe the other OS's are vulnerable as well. And so that was really my biggest disappointment was that they themselves didn't take the initiative to say, hey, like, maybe we should check this. And so, you know, nothing against Google Project Zero. I mean, kudos. And I didn't even look, the bug might have been totally different, but again, from a conceptual point of view, since it impacted Mac OS, it also impacted their other operating systems. And they didn't, again, kind of take the initiative to figure that out once the initial bug was reported. Yes? . And here's Patrick dropping Zoom zero days. Wow. Great question. So the question was, what can Zoom do to improve this? So first and foremost, I have actually a lot of really good friends that work at Zoom, and I have a ton of respect for them. They are brilliant researchers, and I do feel a little bit bad for dropping zero days at them. But, you know, come on, this is DEF CON. Also, you know, as I mentioned, a lot of the other bugs I reported to Zoom really took a very long time to get fixed. And in the meantime, users were vulnerable and were exposed. I'd be very naive to assume that just because I can find these bugs, nobody else could. That's very arrogant. Yes, I have a propensity for finding them, but any other security researcher who's looking at this code would likely find these bugs as well. Especially nation states, hacker groups, et cetera, et cetera. So I think one of the issues is that we as users are not demanding this. I mean, Zoom has a huge market share. It's really popular. If everyone was like, we're going to stop using Zoom until they get their security act together, that would change it. Yeah, so maybe the government can jump in. I mean, this is a great question, and I think it applies to any company. Traditionally, usability is, I think, prioritized, especially by startups. I mean, you can't blame Zoom. They made a gazillion dollars, so their shareholders are demanding that they make money. And security, unfortunately, isn't necessarily incentivized. So until that changes, and again, not picking on Zoom, this is what most companies do, it's kind of like following the money. So I think if there's more regulations, or I remember when Mr. Musk was like, no Zoom at Tesla or whatever it was when some of these bugs were coming out, I think those are the things that change that. So I think Zoom is definitely taking steps in the right direction. But I think there's some responsibility from us to also demand more. And so, you know, maybe us pushing for regulations or talking about these problems at DEF CON, bringing more awareness is ultimately how we kind of change the priorities. Because until the priorities change, companies, including Zoom, are probably not super motivated to go after security. It's not sexy. It doesn't really cost them a lot of money, at least traditionally. So, like, why would they? Maybe I'm jaded. Any other questions? Yes. Yeah, the question was, do I have copies of my book here? NoSearchPress has a table in the vendor area. So you can swing by there. They have a discount. I also will be doing a book signing tomorrow, which is like a big exciting event for me. So feel free to swing by. I'll sign a book and we'll talk nerdy and that will be awesome. All right. Thank you again so much.