 Thank you, uh, Aloha and welcome to my talk, Nothing But Nets. Yes, I am Patrick Wurdle. I am the founder of the Objective C Foundation. Uh, you might know me from some of the, uh, Objective C free open source Mac security tools. I also write the art of Mac malware book series. And finally, organized, objective by the C security conference. So, what will you learn today? What are we gonna talk about? What are we gonna dive into? Well, pretty much four things that really in a nutshell will show us how to leverage, uh, macOS's Apple's networking frameworks to heuristically detect malware directly on, uh, a host. So we're gonna start by looking at some examples of Mac malware that utilize the network, because, well, before we write tools to detect such activity, we should have at least a baseline understanding of, well, what we're looking for. We're then gonna talk about how to take a snapshot, enumerate the network state on a Mac to see things like active connections, open sockets. Et cetera. We're then gonna kinda graduate up to more comprehensive tools that will allow us to continually monitor the network. Both DNS traffic and all traffic, including filtering and blocking certain connections. And then finally, we're gonna end with how to then tie that activity back to processes and determine if those processes are suspicious or malicious, because, you know, obviously legitimate software is also gonna be using the network as well. So we need a way to identify what is unauthorized. Now this is the main idea and this is a very obvious idea, so I'm not claiming this is new and it's just, let's detect malware via unauthorized network activity. This is based on two, again, very obvious, uh, observations, which is first, malware uses the network. How? Good question. In a variety of ways. For example, it pops, reverse shells. Uh, it might use the network to propagate to other machines. A lot of malware, especially back doors, will interact with a command control server and take tasking from a remote source. And now, we're gonna get to that. And now we're gonna get to that. And now we're gonna get to that. So, let's get to that. And now, we're gonna get to that. So, let's get to that. And now we're gonna get to that. So, let's get to that. And now we're gonna get to that. So, let's get to that. Now, let's get to that. So, let's get server. And then a lot of malware will also, for example, download additional payloads or files or exfiltrate up files to a remote server. So again, a lot of opportunities for detecting the malware based on its network traffic. So the idea is, if we can observe this network activity and classify it as suspicious or unauthorized, we should be able to generically uncover malware. Now the way network monitoring is normally done is via placing an application, network application in the network, especially in the context of the enterprise. So this is a separate hardware device that all traffic from the network may be routed through and it can then examine and look for anomalies. And this definitely works. There's some pros to this approach, but there's definitely some cons. So this talk, instead, we're going to focus on a host-based network monitoring, meaning our code is going to run directly on the host. The benefits of this are threefold. First and most importantly is the fact that if we are running on the host where we are observing network traffic, we will be able to identify the responsible process. Imagine you are a network appliance, you see a DNS request, you might not be able to say what application generated this, right? Is this the user's browser or a malicious backdoor? Well, if our code is running on the host and we observe that same DNS request, we will be able to pinpoint or tie that back to the process and then analyze that process to answer the question, is it malicious or not? So that's really kind of the main benefit of host-based network monitoring. It also happens pre-encryption. So if you want to do full packet capturing, well, you don't have to worry about removing SSL certificates, manning the middle, it's just there before it gets encrypted to go out on the wire. And then thirdly, it's more simple and maybe more cost effective. You don't need to buy any additional hardware. And especially recently, a lot of these hardware network appliances have security vulnerabilities that hackers are actually using to get into the network. So not ideal. Now you might be thinking, okay, cool, host-based network monitoring, it's pretty well understood, some good pros, why are we giving a talk about it? Well, a few main reasons. One of them is on macOS there's just really not been a lot of research or examples of how to do this. And there's a variety of reasons for this. One of the main reasons is a lot of the frameworks and capabilities we're going to use are only pretty new. They've only been recently introduced by Apple. There's also a lot of challenges, blood, sweat, and tears that I've been through the last few years developing host-based networking tools on macOS. So I want to kind of share some of the pain points so you all don't have to. So one example is Apple's networking frameworks used to be incredibly buggy. So you write this lovely user mode tool that leverages Apple's documented frameworks and then the user runs it and it panics the box. What do they do? They follow bug reports saying your tool is crap and you're like, is it? It runs in user mode. How can it panic the box? And you look into it and it turns out that Apple has a kernel bog in their networking logic and you're like, thanks Cupertino. Now Apple is pre-receptive about fixing this, but again an example of, you know, kind of a trials and tribulations, let's just say. Other challenges, a lot of the frameworks are private. So you have a very powerful networking framework you want to use, but there's no documentation. There's no source code. So you have to go through and reverse engineer it. Also a pain. And then finally the documentation, super lacking. The other thing that Apple originally did, which was really not cool, was that they actually neutered capabilities themselves. So story time, you used to run network monitoring tools that ran directly in the kernel. This makes sense. That's where the networking stack is. Apple said, we don't want third party kernel extensions anymore in macOS, so we're going to kick you all out of the kernel. But don't worry, we've introduced some new frameworks that your code can link against and utilize to give you the same capabilities. And I was like, okay, this is actually kind of neat. Writing kernel code is a pain in the butt. If there's a bug in it, it's going to panic the box. So yes, I would rather write a tool that runs in user mode if it gives me the same capabilities as before. What Apple didn't tell anybody is they exempted a large number of processes that would not be routed through these user mode networking frameworks. So imagine you wanted to write a firewall that maybe blocked all traffic. Yeah, good luck because Apple's system processes would be exempted from that. And again, they did this without telling anybody, which in my opinion is, well, wrong. So we reversed the engineer and figured this out and called Apple out. Turned out it was trivial to leverage these trusted processes to generate network activity on your own behalf. So once we created a proof of concept that was able to bypass this and reported it to Apple, they said, no, this is functionality by design. Went to the press, made noise, made Apple look bad. They immediately fixed it. So a takeaway, if you want to enact change at Apple, make them look bad. The unfortunate reality. So now as I mentioned, let's look at some Macmower, ones that access the network to get a good understanding of the kind of activity we're going to look for. The first malware sample I want to talk about is called dummy. I named it dummy because it's pretty dumb. But it's simple and effective in a way. So maybe that's a kind of a harsh name. We can see on the slide it's basically a bash script that executes various Python commands that do three things. Connect out to the attacker's remote server. Redirect standard in out error. And then spawn an interactive shell that's tied to those sockets. And again, because the file descriptors for standard in an error have been redirected to the socket, this gives the remote attacker a reverse shell on the infected system. So again, it's kind of a standard vanilla reverse shell. Another piece of Macmower that uses the network is IP storm. IP storm is interesting for a variety of reasons. One of the reasons is it was originally written on Linux. As Macs become more popular, more prevalent, especially in the enterprise, we're seeing a trend of malware authors and adversaries porting or recompiling their malicious creations to run natively on macOS. IP storm is a great example of that. So hackers are definitely taking notice of macOS's increased popularity. Now as we can see on the slide, the quote from the company that did the initial analysis, the malware would propagate from one system to the next by SSH brute force attacks. So the idea is if it could guess the password or brute force in, it would then infect the system. So it had some worm-like capabilities. Again, this network activity, if we can observe that, maybe that's an opportunity to detect this malware. Once IP storm successfully infected a system, it would then open a reverse shell. So again, network activity that we could perhaps use to detect the infection. Another recent Macmower specimen that leverages the network is GoRat. GoRat is a pretty standard but fairly feature complete backdoor for macOS. I've listed its capabilities. You can see it does things like upload files, download files, pretty standard. Howard does have some additional capabilities which we don't commonly see in Macmower that allow it to interact with other systems via the network. For example, it has the ability to generate a port scan. So again, if we're interested in detecting malware via network activity, if the malware is generating port scans of remote systems, maybe that's something we can pick up on. It also has the ability to set up tunnels and proxies, more network activity for us to detect. It's also worth talking about supply chain attacks. These are becoming unfortunately ever more prolific. And again, the adversaries are now starting to target macOS systems. Normally, supply chain attacks mostly impacted Windows systems. A great example of this, of a supply chain attack attacking and targeting mac systems is 3CX. What happened is an APT group associated with the North Koreans broke into 3CX, which is a popular PBX software for the enterprise. They installed a macOS backdoor on 3CX's build server and trojanized 3CX's desktop application. This meant when users around the world downloaded the update they would inadvertently get infected. One thing to note is before the adversaries did this, after they infected the installer, but before they distributed it, they actually sent it to Apple. And this is because in recent versions of macOS software has to be notarized, which means Apple has scanned it and given it their stamp of approval before it will run. So the attackers took a little bit of a gamble here, essentially sending the infected installer to Cupertino. Apple happily notarized it. Less than ideal. So how was 3CX, how was the supply chain found? Because again, super stealthy. And the payload is, you know, signed and notarized. Well, it turns out via network traffic. So as we can see on the slide from the 3CX forums, the user basically said, hey, one of my EDR products noticed anomalous DNS requests generated from the 3CX application. So again, this kind of drives home the point of the power of network detection and especially in the context of supply chain attacks, this is probably the best approach for us to detect intrusions. Speaking of best approaches, also worth mentioning iOS. Now this talk is predominantly about macOS, but a lot of the techniques we talk about, the frameworks also exist on iOS. So it would be not that difficult to write similar capabilities on iOS. Now to detect malware on iOS, you're basically SOL because iOS is so locked down on a non-GL broken iPhone, you can't even get a list of running processes. So like, how are you going to detect malware? Unfortunately, nation states have zero click, zero day vulnerabilities that allow them to infect iOS devices by merely knowing someone's phone number. So anywhere in the world, they can hit you. And once they're in, yes, that's a hard target to get into, but they can actually leverage the security of that system as a protection mechanism. For example, I just mentioned you can't run a list, a process listing. So the adversaries, once they're in, they're like happy. An example of this is Kaspersky and the triangulation malware, this recently came out where an unknown adversary hacked into corporate and employee devices of Kaspersky, the Russian antivirus company, and remain undetected for four years existing on their iOS devices. That is insane. Kaspersky is one of the top security EDR, AB companies in the world. They did not detect an infection on their own systems for four years and that's not their fault per se. How do they eventually detect it? Network traffic, as we can see on the slide. So again, if you're doing malware analysis on iOS or malware detection rather, network is really the place you want to be and perhaps the only way you're going to detect, especially these more stealthy and advanced attacks. Okay, so that gives us an overview of macOS malware. Hopefully you've illustrated that we really want to be looking at network activity, because again, most of the malware is going to generate something that's observable. So now let's talk about how to enumerate this network activity starting by using file descriptors. The idea is pretty basic and that is on macOS, very similar to BSD and some other Linux-like operating systems. File descriptors are kind of everything, meaning sockets themselves are also file descriptors. So what we're going to do is we simply query the operating system, we specify the process ID of a process we're interested in, and the operating system will give us a list of file descriptors that that process has open. What we can then do is iterate through that, focusing only on sockets, right? We don't really care about normal file descriptors. And for those sockets then, we can query the operating system again to get information about those. So here's the example code. I'm not going to walk through the code because I don't think you want me up here like going line by line, but you know, I wanted to put this up here for, you know, like as a resource, so later you can go back and check it out. But I'll briefly describe some of it. So on the bottom, what we're doing is we're invoking the proc-pid-info API. We invoke this first with a PID. The process we're interested in file descriptors. And then a bunch of nulls. The operating system will return to us the size of the buffer we need to allocate to store the file descriptors in memory. We allocate that buffer, call that API again with the size and our newly allocated buffer. And voila, we get a list of the file descriptors that the process has opened. Again, this is going to include normal files but also sockets. Now what we're going to do is we're going to iterate through all of those file descriptors and we're going to focus on those that are just sockets. So you can see again some example code that implements this. For each file descriptor that is a socket, we then call the proc-pid-fdinfo with that socket file descriptor to get socket-specific information. From that, we can now examine the socket. The first thing we do is we make sure it's a networking socket. On macOS you can also have UNIX sockets, which are local sockets used for IPC mechanisms. We don't care about those in the context of detecting MacMower. So you can see on the slide we focus on AFINET or AFINET6, IPB4 or AFINET6 sockets only. If we compile this code and run it, I run it against the GitHub desktop application that's running on my system. We can see it found 70 file descriptors and has filtered out those that are sockets, which is a very small subset. Why am I using GitHub desktop? Great question. It's obviously a legitimate application. This is not malware. It's easy to test with. It has a lot of legitimate connections. I always like to test my code on legitimate software before trying it on MacMower. And also, it illustrates the point that legitimate applications obviously are going to use the network as well. So now that we have a network socket, we can start extracting relevant information from that. If it's a UDP socket, there's not a ton of information because it's stateless. But we can at least, for example, extract the local port. For TCP sockets, there's tons more information available to us. Again, I'm not going to walk through all this, kind of some boring code, but you can see we're able to extract, for example, the information about the remote endpoint, the remote IP address and remote port. Clearly, you can see if we're trying to detect malware, this is useful, right? Where is this application talking to? Is it a command and control server in North Korea? Okay, that's a big red flag. Or is it just some well-known trusted endpoint? So if we compile and run this against GitHub desktop now since we're extracting all the socket information, we can see all the information about GitHub desktop's network activity. So socket details such as the family, the port, the protocol, remote local information, et cetera, et cetera. So now if we run this code against or on a system that is infected with OSX dummy, we can see that this code picks up the fact that there is a established connection on port 1337. Yes, this is the port the malware uses to some remote command and control server. And you're like, okay, that's interesting. Now we can determine that. But, you know, dummy as we know uses Python to set up the reverse shell. So the question is how can I tell from solely this network activity that this instance of Python is being used maliciously? Great question. We'll get to that shortly. Now let's talk about enumerating network state using the private network statistics framework. And the reason I want to talk about this other way is that it has some additional pros over the method we just talked, the file descriptor method. So via the PROC PID API method that we just talked about, a few kind of perhaps downsides to it, it's process specific, so you only get the file handles for the process you specify. Of course you can just enumerate all the processes and make the requests for each one, but that's some additional code. Also, we get all the file descriptors, so we had to add additional code to filter out the sockets. Again, totally doable, but extra code. Most notably though, it doesn't provide us any statistics. Like, I want to know how much data, how many bytes a network connection is responsible for. For example, is an application exfiltrating gigs of data? That's super interesting. We cannot determine that from file handles, file descriptors alone. So what do we do? Well, it turns out there's a very interesting utility that's built into Mac OS. It's an Apple utility called NetTop, and if you execute it, it gives us all the information we're looking for. So it's global, so it's for every process. It's just sockets, so we don't have to worry about other files. And also it provides statistics, how many bytes up and down each connection is responsible for. Unfortunately, this utility is closed source, so we can't utilize it programatically very easily, but if we look at its dependencies, the libraries it's linked against, and we can do that with the O tool utility, we can see that it's linked against a private framework called network statistics dot framework. Now, the well-regarded noted security researcher, Jonathan Levin, actually fully reversed engineered this framework and wrote a nice open source command line utility leveraging this network private framework. So you can check that out. I love that, but I wanted a UI version. I wanted a tool that a user would be very easily able to double click and see all network activity on their system. So the first tool I want to talk about today is called Netacit. It's built on top of the private network statistics framework, and it's a nice UI. It's a pretty simple tool, but it will show you all the network activity on your system, a snapshot of that, kind of organized by process. You can also see information as you would expect about the interface it's bound to, the state of the connection, but yes, also bites up and down. If you're interested in learning more about this tool, pop over to the Objective C website. It's free, fully open source. But let's look briefly at some of the code behind it, the code that interacts with the private network statistics framework, because it's actually pretty straightforward. So the first thing you have to do is create a end stat manager, a network statistics manager. You allocate that. Once that has been created, you set a callback block via the end stat sort set description block function. And we'll get to that in a second. Then you tell the operating system that framework that you're interested in all TCP and all UDP connection. There are APIs for that. And then what you do is you start a query. This tells the operating system to call the API in the framework and enumerate all current network activity. And for each connection, it will invoke the callback block that you've set. So here we just call NSLog, which will print out information about that. We then link in the network statistics framework and run it. What information do we get for each connection? A ton, which is great. Detecting malware, the more information we have, the better. So here are the details from one single connection from GitHub desktop. A little hard to read that's kind of by design, just to show you how much information this private framework gives you, again, for every connection on the host. You can see the responsible process. Again, this is something we really are interested in. Is it malware or is it, you know, GitHub desktop? We also get the transmitted bytes up and down. And then if it's a TCP connection, a ton of information about the connection as well. So a really powerful framework to use. Now, there's always pros and cons to everything. So I always like to point out some of the downsides. And the biggest downsides to the two approaches we've talked about so far are that they only provide you a snapshot of the current state of the network on the host. Why is this problematic? Well, if malware is sleeping or only beacons out once an hour and you perform your snapshot of network activity between that, you will not see the network activity associated with the malware. And this is actually very common. For example, both dummy and some of the 3CX payloads utilize sleep or beacon or connect out on certain intervals. So again, perhaps our tools might miss them. Now, of course, you could take a snapshot every five seconds, but that might be somewhat resource intensive. And also you still might miss the malware. So what we need to do now is kind of graduate up and talk about more comprehensive tools that allow us to continually monitor the network. So at any time if the network or a malicious piece of software tries to access the network in an unauthorized manner, we will be there to observe it. So let's start by talking about how to build a DNS monitor that's going to run natively on macOS fully in user mode. The idea is pretty straightforward. The majority of malware, regardless of how it gets onto your system, is going to connect out to a remote server and most malware does that via domain, which means it's first going to have to resolve the name. Sure, we all know how DNS works, but a quick recap. The malware tries to connect out. This generates a DNS request to the DNS server. The DNS server returns the IP address and then the malware connects out to the IP address. So the question is, is this a good approach to detect malware? And I think the answer is yes, it's very efficient because again, most malware is going to be generating DNS requests. We don't have to monitor all network traffic. And in the case of some very stealthy malware attacks like the 3CX one, this was actually how the malware was detected in the first place, anomalous DNS requests. So how do we build a DNS monitor for macOS? More generically, how do we build these monitoring tools that allow us to continually monitor the network? The answer is to use Apple's network extensions framework. This is a pretty new framework that Apple now affords us to use. I believe originally was available on iOS, but now you can utilize it on macOS. And like some of the other frameworks and APIs I've talked about, this is actually decently documented. So kudos to Apple here. You can read on Apple's site all the cool things you can do with network extensions. They're actually incredibly powerful. We're going to focus on the last two, specifically how to intercept DNS traffic. And then we're going to talk at the very end about how to filter all network traffic. So again, we can use network extensions to do both of these. There's a great WWDC video where Apple explains exactly how to use these. Have a watch. So in order to build a DNS monitor, we actually are going to use a DNS proxy class. And that is the NEDNS proxy manager class. So I saw this in the documentation and it says, hey, this will allow your application to intercept all DNS traffic. Perfect. How do I do this? So I write code by Googling things. And so I just Googled it and there was like two hits. The first one was Apple's developer documentation that kind of described the APIs, but not much more. And then the second hit was like, hey, y'all, how do we do this? So I was like, oh, well, other people are in the same boat as me. There's no example code. There's no great documentation. So this could also be a learning experience for me. This is a tool I want to write anyways. So I saw that there would be some other interest as well. I'm not the only person who wants a host-based DNS monitor from macOS. There's at least one other person. So worth it. So the tool I wrote is called DNS Monitor. Again, fully open source free on objectivec.org. And you see when we execute it from the terminal, if we then resolve a DNS name, for example, objectivec.org via NS lookup, this will generate a DNS request that we can intercept. Now, unfortunately, there are several prerequisites. So if you're interested in writing your own network monitoring tools, which you should, it's great fun, there are some hoops you have to jump through, unfortunately. So first, you have to have certain entitlements that Apple may or may not give you. So be prepared to beg. Also, then when you build it, there's a lot of constraints. Specifically, you have to put your network extension in a certain place of the application. So building the project can get a little hairy. And then, of course, you have to sign and notarize this. So this means you have to at least pay Apple a few hundred bucks for the developer ID and get them to validate and notarize it. Okay, now you want your user to run it. What do they have to do? Click a lot. So if you go to objectivec.org and download DNS monitor, which is entitled, which means Apple gave me permission to do this, it's signed and notarized, which means Apple has scanned it and verified it. You still have to click allow. This is fari prompt. When you open it, gatekeeper is going to bug you, so you have to click allow there. When you go to launch the app, it's going to say, hey, wait a minute, this is a network extension, instead of a system extension, you need to improve that. So you have to click open security systems. You then once in there have to improve that, which is going to require you to authorize. So you're going to have to put in your password. And then finally, before it's able to access the network to monitor traffic, you're going to have to click allow one more time. So this is slightly annoying and if you're writing code, you have to handle all these situations. Like what if the user clicks no? You have to handle code to maybe do this again or fail gracefully. So this is a little annoying. And at this point I'm like, man, macOS has really become like Windows Vista. You might not be as old as I am. So you might not remember Vista, but Vista was like this Windows operating system where you had to click allow on everything. And everyone like made fun of it, guess who made the most fun of it? Apple. They made these hilarious commercials basically ragging on Vista for having a user's click allow. And since you might not remember that, I have the commercial here that we are now going to watch. So I hope the audio works. If not, they're subtitles. Hello, I'm a Mac. Mac is issued a salutation cancel or allow commercial. Allow and I'm a PC. You're returning Mac salutation cancel or allow. Allow quite gives Mac is asking question cancel or allow allow. He's part of Vista my new operating system. PCs have a lot of security problems. So he asked me to authorize pretty much anything I do. You're pointing out Vista's flaws cancel or allow allow. I could turn him off, but then he wouldn't give me any warnings at all. And that would defeat the purpose. So you were coming to a sad realization. Cancel or allow. Hello. Hilarious. So I don't know if you were counting, but there was five allows. How many allows did we need to install a network extension? Six. So, you know, come on Apple. If you're gonna like rag on Windows, like don't become them. Now we're not here to pick on Apple too much. So let's get back to some code. But that was some good comic relief. So let's talk about how to activate a system extension. And network extensions are a subset of system extensions. So any network extension is also going to be a system extension. So again, not going to walk through the code too much. This is more of kind of a resource, but at a high level there's three steps. You basically are equate generate a request to activate a system extension. You then set your delegate. This is a class that's going to handle various methods that the operating system will invoke. And then finally you submit the request. This is what's going to generate one of the props pop-ups and if the user approves it, your system extension is going to be off and running. Now, though, we also want to monitor network traffic. Again, we're having a network extension. So what we need to do is we need to activate the network extension. This requires five steps. We load the current preferences. We set a description. We initialize and configure a provider protocol. In this case, we're using the N-DNS proxy provider protocol because we want to proxy DNS traffic. We set a flag to enable and then we save the preferences which triggers another pop-up that the user has to approve, which then, if they approve, will activate the network extension. At this point, our network extension will be off and running. You can confirm this using Apple's system extension control utility with the list command. If we do that, we can see that our DNS networking monitor has been loaded. Behind the scenes, what Apple has done is copied it from your application bundle and moved it into a route-owned directory and loaded it from there. So this is one of the reasons you have to be very careful about packaging up your application that contains the network extension because the operating system needs it to be in that specific location. Okay, so now we're off and running. That code so far was executed in our application. Now, since our network extension is loaded, it's going to be running as a separate process in the root session, we need to start monitoring DNS traffic. So the first thing we do is we call the start system extension mode function. Apple says do this right away. I don't really know what it does. Kicks things off. Behind the scenes, MacOS will consult the info.plist file of the network extension, which you will have to set up in a way to specify what class in your program is going to implement the delegates, for example, to handle new DNS requests. So on the slide, we can see how it would do that. So what are these delegate methods that this class has to implement? Well, there's three. There's a start one and a stop one. This just gives you the opportunity to perform any initializations or cleanup. The most important one is the handle new flow API method. Apple's documentation says this will be invoked any time a new DNS flow, which is essentially a connection is generated. Perfect. Now, remember we are building a DNS monitor, but we're using this proxy class, which means as a proxy, we are actually responsible for, well, proxying on the data. So what we have to do is six or so different steps. And I'll walk you through that. So an application or some malicious software needs to resolve a domain. So they do that, that generates a DNS request. Before that DNS request goes out to the DNS server, because we've installed a network extension, the operating system is going to deliver it to us. It's going to call our handle new flow method. What we have to do is open the local flow, read the datagrams, which is going to be a DNS question, a DNS query, and then connect out to the DNS server ourselves, build a new connection, and then write the datagrams, the DNS request out to that remote endpoint. So we are basically responsible for taking it and now delivering it, because again, we're proxying the request. This also means we're responsible for reading and delivering the response from the DNS server. So the next two steps are, we read the response from the DNS server, and then write it to the local flow, which means it will then be delivered to the local application or the malware whoever generated the DNS request. Now you might be wondering, okay, that's cool, but how do we parse the DNS packets? And this is a question I had, and I thought, do I have to do this myself? And I tried and then I was like, wait, this is a horrible idea. There's probably got to be a better way. Turns out there's a relatively unknown library called Libresolve, it was at least unknown to me, that ships with macOS that you can link into your application or your network extension and you can parse DNS packets. So on the slide we have an example of that. We give it a packet, a DNS request or response. We call the DNS parse packet, and it returns to us a structure with all the members of the DNS nicely parsed out. This is super helpful. Definitely use this library. What we haven't talked about yet is, how do we identify the process that was responsible for generating the DNS request? At the beginning of this talk I said, this is the best thing about host-based network monitoring. And, well, it is. So how do we do that? Turns out it's pretty easy. The flow object that gets passed to the handle new flow method has what is known as an audit token that uniquely identifies the responsible process. The application, the malware, whomever is trying to make the DNS request. Audit tokens are kind of modern ways to uniquely identify processes that are more secure than PIDs. But once we have this audit token we can retrieve the process's PID, its path, et cetera, et cetera, anything about that. So that's really helpful because that can allow us to identify who is responsible for that DNS request. So when we compile and execute this code on a system that's infected with 3CX we can now see that when, again, this very stealthy supply chain attack is executed, when the malware tries to connect out the Trojanized installer, connects out to the attacker's command and control server, we can observe this and say, hey, wait a minute, this isn't 3CX, it's talking to some MS storage boxes.com, big red flag. Now via the DNS monitor we can also do things like block DNS requests or responses because, again, we're proxying all the traffic. So this is great if we want to build perhaps a more proactive security tool. So let's look at how to do that. Super simple. What we do is we get the DNS request via the handle new flow API that, again, is going to be automatically executed for each new DNS request. We parse that packet using libresolve and then what we can do is we can extract the question, that is the domain that the application or the malware is trying to resolve. And if it's on a block list that we specify, we simply close out the flow. This means that the connection is actually never going to go out and from the applications point of view the DNS resolution has just failed. So if we implement this in the DNS monitor, we can now see that if, for example, I've told it to block Google.com, if we try to resolve Google.com via, you know, NS lookup or any other way, it's just going to time out and the system is going to be like, I can't help you. So this is great. This means now if we know the command and control server we can block where the malware is trying to connect out to. It won't be able to resolve it and then won't be able to connect out. We can also block the answer. The answer is going to be the IP address that the domain resolves to. So perhaps we might not know what all domains malicious IP address is mapped to. As long as we know that the IP itself is suspicious or bad. When the answer comes back, the answer recall is proxied through us before it gets back to the application. So again, we can simply say is this something we want to block and if so close the flow which will have the same effect the application will never get the response. Last feature of DNS monitor, you can dump the cache. This was actually one of the features I wanted the operating system to give me and one of the reasons why I wrote this tool. So what we can do is we can send a signal to the DNS monitor and it will basically dump all its records, all the domains and the IP addresses for all the queries on the system. This is great perhaps as a troubleshooting DNS troubleshooting tool. Now there's one short coming. Again, pros and cons, everything's a package deal and that is that we are only going to see DNS traffic. So let's turn our eyes back to dummy and if we look at line number six, we can see it connects out to the attacker's command and control server. It uses a hard coded IP address which means what? No DNS traffic which means we will not see any of dummy's network traffic because it doesn't need to use DNS. So the next question is can we enhance our DNS monitor or take a more comprehensive approach to see all network traffic? The answer is of course we can do this and also throw in some rules to build a utility such as a firewall. So Lulu, you might be familiar it's been around for a while recently updated it to use Apple's new network extensions framework. Previously it used a kernel extension and well it's a firewall, right? I don't need to explain this but the idea is it sees all network traffic and if it's from an authorized or trusted process it allows it. If it's something that it doesn't recognize it prompts the user to be like yo something's happening confirm or deny. Oops, maybe I do it too. All right, so how do we do this? We use another class that the network extension APIs and library affords to us which is the NE filter data provider. This allows you to monitor and govern all network flows as we can see from the header file description. The idea is all network traffic comes to us and then we can classify it as benign, authorized or perhaps suspicious and malicious. The way we do that and we'll dive into that shortly is by either looking at the responsible process, we can do some analysis on the traffic itself or we can ask the user. So very similar to the DNS monitor we need to enable the network extension by again these four steps. There's a few differences here since we're monitoring all network traffic we have some more customization capabilities including the fact that we could in theory monitor or rather examine all packets. For firewall we don't want to we just care more about the connections so we say no. However, we do say we want to filter all sockets so we set that to yes. Once we've saved these configuration changes this will activate the network filter and all network traffic will now be routed through us. Again, the handle new flow method will be invoked. Apple describes the handle new flow method it's pretty similar to the DNS monitor with one separate or new thing and that is it expects a response from us whether to allow or deny the connection. So there's three answers you can give and you have to give an answer either block which will cause the operating system to drop the connection allow it which will allow it or pause it for example if you want to ask the user and then you can resume or block it at a later time. Now if you want a passive monitor you just click or return allow for all connections. Okay, so now maybe the most important part of the talk, the conversation is okay now we have the ability to take snapshots of network activity, traffic, look at DNS traffic or even monitor all system traffic. How do we, and this is an incredibly important question determine if that traffic is unauthorized, malicious, belongs to something that should not be on the system talking to the network? So let's talk about some heuristics. I mentioned there's two main ways three if you ask the user but let's just focus on two here. The most common way and this is well established is via the network information that is provided in the flow. Now there's been talks about this, books written on it, this is how most network appliances classify network traffic as being unauthorized or not. So things like state, right? Like a listening socket bound to the external interface on port 1337 or 666 like big red flags, right? Also maybe statistics is something beaconing every hour or perhaps once a day at midnight and uploading a gig of data to some unknown endpoint. That's suspicious. But again, since we're doing host based traffic analysis and running on the host we can also bring in the responsible process. Perhaps for example that process that's beaconing at midnight and sending a gig of data somewhere is the backup solution just backing up the user's files at midnight and that's fine. You will not be able to tell that from a network application or network appliance. But if we're on the host we can say, hey, who is doing this and answer that question conclusively. So let's talk about now how to examine that responsible process to perhaps determine if it's malicious or not. Now I will caveat there are many ways to do that. That could be a talk unto itself but let's look at some recent examples that would at least be able to identify the malware samples we talked about earlier in the talk as, well, malware. So some examples, you know, is the item that's running a non-platform binary? Is it something that's non-notarized? Is it persistently insolved? Perhaps a red flag. And is it doing something unusual for example with the process hierarchy? So let's look at that. The first one is how to determine if something belongs to Mac OS proper in Apple parlance. They say that's a platform binary and also if it's notarized or not. So notarization I talked about is a method where applications, programs are submitted to Apple and they are approved. Yes, Apple sometimes inadvertently approves malware but generally speaking, all legitimate third party software is mostly notarized whereas most malware is not. So this is kind of a good, pretty solid red flag if you see something that's not notarized. Not gonna go through all the code but once we have an audit token for the responsible process or even a PID what we can do is we can invoke various code signing APIs in Mac OS to ask questions like is this an Apple binary? Is this notarized? And then the operating system will figure that out and give us an answer that will allow us to well answer this question. If you're interested in the full implementation I wrote a utility called block block which does some other stuff but it also has a full implementation of this code. Next question, is it persistently installed? The majority of Mac malware is going to persist so if you see a network connection that's tied to a persistent process maybe cause for concern or at least something you're gonna wanna look at a little closer. On recent versions of Mac OS persistence is governed or managed by this undocumented background's item database. I wrote an open source utility that will deserialize the items in this database and print them out for you. So this for example is what dummy looks like in the database. So OSX dummy persists as a launch daemon. It's component as we saw is a script that will run as root and since it's a script it's not signed. So we have a persistent script running as root. That's not common, that's cause for concern. And then finally and we'll stick with dummy here you should also look at the process hierarchy. So at the very beginning I posed the question how do we know that this instance of Python is malicious or being abused rather? Well if you look at the process hierarchy for it you will see that Python is a child of bash which is a child of launch d meaning that it has been persisted and then executed via bash. We can also see it's running as root. So now what we have just to put everything together we have a established connection to some unknown IP address on port 1337 strange. It's tied back to a script that's running as root via Python that's spawned via bash that's persistently installed. Like all those things are kind of individually strange but then if we combine them all together that's a huge red flag. 99% of the time that's probably gonna be malware at least something you want to take a closer look at. All right so let's conclude this and wrap this all up. So hopefully I've illustrated to you that by leveraging macOS' networking frameworks we can heuristically detect malware directly from the host. Again this is based on the very keen observation that malware uses the network and so if we can detect this unauthorized activity we can uncover malware. If you're interested in learning more I've written a book on analyzing mac malware. It's 100% free on taomm.org for the art of mac malware. I'm also writing another volume which will be about the programmatic detection. So think this topic plus many more. This will also be free as well. I'm gonna be doing a book signing tomorrow on volume one at the no starch press table at 11 a.m. So if you wanna pick up a copy of the book or have me sign it, stop by and say hi. I wanna end by briefly talking about our organization because I think it's amazing and I'm super stoked. So the Objective C Foundation is a non-profit and we do some really cool things that I just wanna share with you because I'm excited about it. So we organize the OBTS security conference. I look around and I see many familiar faces from the conference, speakers, attendees, you haven't heard about Objective By The Sea. It's awesome. We also generate raised money for college scholarships for high school students and have some diversity programs which we're really stoked on as well. So again, pop over to ObjectiveC.org. Now I wanna end maybe not on the happiest note. Many of you know I live in Maui. The Objective C Foundation is born in Maui. The OBTS conference started on Maui. I made all these slides on Maui. And earlier this week, there were some really catastrophic wildfires on Maui. Many people died, lost everything. So what we're doing is we are launching a fundraiser through our non-profit, our 501-C3 to raise money for that. So if you're called to support a great cause, check that out or just even pass, share on the link. 100% of the money is gonna go to the residents of Maui that have literally lost everything including loved ones. So again, pop over to ObjectiveC.org to get some more information about that. Finally, I just wanna thank the companies who support the ObjectiveC Foundation. They're the ones that allow us to organize the conference, support my research, allow me to be able to write a book and make it free. The goal is really for us as a foundation, me as a researcher to empower the community, share my knowledge and that is, I'm able to do that because of these companies. So just again, I wanna end by thanking them. I also wanna thank you for sitting through my talk. Really appreciate your attendance. Think I'm out of time so maybe no public Q&As but I will pop over here and since this is the last talk of the day we can hang out here as long as y'all want and so if there's any questions, come ask away. Again, thank you so much. I really appreciate y'all being here.