 My name is Conor Moly, this is Lacey Fan, we are Threat Hunters with Cantercept and we're going to be doing a presentation here about KillSuit. So what exactly are we going to be covering today? We're going to be covering what KillSuit is, what it does, what happens when it's installed into a system, how to detect and remediate KillSuit, how KillSuit persists in the system using its advanced boot kit solar time and how to detect and remediate a solar time infection. So first things first, what exactly is KillSuit? So KillSuit is a post-exploitation framework that was developed by the Equation Group prior to 2013 and leaked by the Shadow Brokers in the Lost in Translation leak in 2017. It's supposedly developed by the Equation Group which are strongly associated with the NSA although not confirmed, so it's likely a state-sponsored actor level attack framework. We know this is in the Dan Spitz framework which was inside the leak and United Rake which has direct references to it inside its instruction manual. So this is basically an overview of what KillSuit is, so what exactly does KillSuit do? So as we mentioned earlier it is a post-exploitation modular capability mechanism. It's a bit of a mouthful but we've done a diagram to basically outline what this means. Effectively the Dan Spitz framework uses the fuzzy bunch exploitation collection in order to pwn a victim to install a pedal cheap agent which is their advanced like C2 channel which then allows them to install a KillSuit instance which has an underlying KillSuit modules which allows for a certain functionality. Now the modules all have individual functionalities and the instances have individual functionality. They can't hear me. Can you hear me now? Yeah. Fantastic. Sorry about that. Where was I? Yep. So the individual modules all have individual capabilities and so do all the instances. Some of these can include persistence of the pedal cheap agent which is like a priority for the Dan Spitz framework as it allows persistence of their C2 channel inside the victim. Each instance and module type has a different codename. This is a list of the codenames that we know about. They all have different functionalities such as strange land which is a Kovac key logger, magic bean which is a Y file man in the middle attack, capability enablement or dark sky which is a package capture utility which is a module type. Now we've gone over modules and instances. Basically this is the way that they fit together. So you can have instance types which have individual capabilities but you can install separate modules under them which allows multiple instances to have the same capability. So in this diagram you can see that SOKN which is Sombernave and WRWA which is Raythrath both have the dark sky module installed which means that both instances have the capability to do package capture. Whereas magic bean and Sombernave which are the two on the left. The one on the left has Flu Avenue which is FLAV which is the IPV4 custom made IPV TCP stack that the guys use in order to avoid detection and DMGZ which is doorman goals which is the IPV6 variant. So you can have lots of instance types which have different capabilities and you can install separate modules under them to have either repeated or specific functionality. You're seeing the right we also added custom modules. That's because the Kilsu module library had the capacity to add new modules. But we didn't actually find how they built these things or the sort of language they used. They used a custom scripting language to begin with and they moved over to Python. So although these modules it has the capacity to load new modules that have never been seen before we couldn't actually find a way to build these or put them in. So if anyone wants to have a poke at that that'd be great. For the main research for this for the instance types and the module capabilities a guy from Francisco De Nozo is one pioneering this. So we do recommend looking at his work because that's basically where he focuses. We have a focus on basically detection of Kilsu when it's installed on a system. So we are going to look at what happens when Kilsu is actually installed on a system. So we did this by obviously creating lots of victim machines and an operating machine pining using fuzzy bunch and then installing Kilsu to see exactly what happened. For an example of so we had to condense this down but one of the main things that we saw was that we injected into a calculator process using double pulsar and this created this sort of action when Kilsu was installed. I call this the Jones Bond function but basically it's a NTML hash generation which happens inside calculator which as you might imagine there's no reason it should be generating hash years inside calculator. Now that's anomalous only in processes that shouldn't do it. So by default, um, then it's actually injecting to LSAS. So LSAS generating hash is not so anomalous. Calculates are very anomalous. So depending on where the operator decides to inject into, it's quite detectable or not. So it's not a be or end or. However, what it and did with that hash was more interesting. So we actually traced where that hash was used inside the process and we found that it basically was used to inject or modify this registry key, OEM management. Now OEM management doesn't actually exist. There's no real reference to that registry key that we could find and we found that that's actually where it installed the encrypted Kilsu database where it basically installed its capabilities. Now in the bottom there you'll see that we've got a KS module store route. This was basically generated using an internal tool for the framework called Double Feature. Double Feature is used by the operators in order to basically verify what is already on their system in a network that's being attacked so that two operators don't necessarily own the same machine. They can see if something's already being installed. Now the KS module route actually corresponded to OEM management. Obviously in this slide the ones with Ki's can see that it doesn't match and the reason for that is there are a lot of variations about where it put this. These are just some of the registry locations that we found while experimenting. Now you might see that the second half where it says cache CFG config is actually repeated and it's split by a capital letter. Now we found that actually the first half and the second half were actually repeated quite frequently and eventually it started to basically recur on itself. So we came to the conclusion that this was um more or less two lists that were being concatenated together and randomly or systematically selected at installation. So we concluded that if we could find these two lists with inside the framework or the binary we could therefore generate every combination and have an easy IOC identify where the KILC was installed and basically just sweet registries to be able to find this. We wanted to prove that this was what we thought and we did this by finding the concatenation operation. So we found that the registry location had two separate strings that were then concatenated together and then added to the end of the registry to verify that this was in fact what we thought it was. So hooray. So we broke down basically where we're going to investigate to try and find these lists. And it broke down into three areas. Um basically whether the communicate whether the operators framework communicated the location to the active uh petal chief agent to install the KILC. Whether the petal chief agent when it was in its DLL form for being injected by double pulsar had it hard coded. Or whether the payload uh the petal chief agent had both lists already in it and then decided basically to uh on the victims uh its victim system variables what options it was going to pick. Now we very quickly eliminated that it was hard coded into the payload because reuse of the payload didn't generate the same results it still was randomized. So definitely not hard coded. So we started looking at uh whether it was communicated from the Tucker. Now in order to do this we had to basically break down uh how the commands were used inside the inside the framework and how it was then transmitted to the agent. And it breaks out of this. The downspits user interface was then communicated to the uh Demi library which is decibel minute. Uh this was then handed off to the Dundaspray or DSZ library which in turn communicated with the primary uh the primary binary which is the DDZS core uh SC core which communicated with the petal chief agent on the inside the victim which then uh enacted uh Kilsu capabilities. So we looked at the decibel minute library to start with uh we quickly came to the conclusion that decibel minute uh was actually used for all of the uh Kilsu operations. One of the libraries that this one is inside the Handle Connect is actually um uh is responsible for uh dynamically loading and unload module drivers inside a Kilsu instance. So this particular uh function allows for um changing of the modules inside an active Kilsu instance. But from the bit that I've highlighted you can see that it actually hands off uh to a uh MCL dot tasking RPC perform call and this is inside the Dundaspray library. Now the DSZ library in turn calls a hidden underscore uh private underscore DSZ library. Now this is where we actually run into a bit of a problem. The underscore DSZ library and the function inside it would nowhere inside the framework that we could find. So all of the libraries were uh python based and this underscore or any of the functions were not in there. And that created a real problem because this was primary to how it communicates with the pedigree pageant. So we started looking and because we couldn't find it inside the framework itself we started looking in the binary. We uh started to analyze the binary and we found that it did have error captures for particular functions inside that we knew were inside this private library but the uh function locations that we found for them were all empty. So a bit more extra research by one of our colleagues Alex Konica uh found that it was in fact a C python module library that was loaded at runtime which is why we couldn't find it statically. So although we were trying to statically analyze it it wasn't there. So we moved on to dynamic analysis to the binary but we ran into even sectionary problems. Now whoever built this tool uh the equation group um they really didn't want this being analyzed. They put in quite a lot of things to prevent us from analyzing it. One of them was that it detect detected debug hookers and if it found one it would instantly terminate. So that was just an indicator of they don't want us to connect this. We were actually able to hide the debugger and get it to run anyway but all the memory locations that we found that were allocated to the function including the index root for the functions there were multiple and a lot of them were dummies and even the locations for the variables we found that the data was either loaded and unloaded so quickly we couldn't find it or we couldn't find the true variable that was actually looking for which was extremely annoying. So we actually reached the capability of our analysis and we had to conclude we don't know if it's there. Which was very unfortunate. So we came to conclusion of although we've got to the end of our capability we're not sure it's there but if we can eliminate that it's inside the payload at least we can focus on one particular area. So we moved on to whether the payload was deciding it from uh environmental variables inside the target. However this created another set of problems. So the binary when it's injected is actually encrypted and um looking at the stack of the process injected into the variables we were looking for for killsuit operations where instead of being as far as we can tell instead of being injected into the process we're injected into kernel data. Now we couldn't figure out how it did it we couldn't figure out why it did it and we couldn't extract the variables we were looking for which again created the situation of we don't know if it's there which made us very upset. So although this came to the conclusion of we have a lot of uh possible variations of the of the combination of the tutors we have we couldn't actually find the tutors within the system. Now if anyone does have expertise in this area please talk to me because we really want to find this list because that would be really awesome. But although we couldn't find these tutors we were looking for we didn't let it stop us and we carried on anyway. And in doing so we came across this which we found was um a check that was made against every fresh killsuit installation on a fresh pedal cheap instance on side of victim. And it does this um cryptographic default provider type of type 023 registry check. Now the first thing of noting is what exactly is a cryptographic provider type? Now a cryptographic provider type is basically a plug and play function or a plug and play description inside the registry which explains how certain encryption algorithms are to be used with certain variables for specific outcomes. Now this is under the windows default and it has a number for AES, DSS and Diffie Hyman things like that. And it has versions 1, 3, 5, 12, 13, 18 and 24. It does not have a default type of 23. This was confirmed by looking at Markz's documentation as accurate as that can be. Um but we found we also found no trace of any legitimate form of uh type 023 within the default provider types. So we had something that was consistent across all infections and something that could be easy checks for using registry monitoring. So we had a consistent um point of installation that we can monitor for using this type 023 and we had a semi conclusive way of monitoring for legacy installations using the registry locations that we generated. So moving on from how we actually did the research, how to detect and actually really remediate Kiehl's suit using this information. So it breaks down into the type 023 default cryptographic type that I just explained. The system function 007 which is the anti-malhash generation depending on which process is injected into. That has obviously quite a big variable for hit and miss depending on what the operator is injected into. And the uh registry directory that installs the encrypted database. Again that's semi conclusive at the moment and not very conclusive. You'll see that there's an extra box there and that's because in the final sweep of the framework we found that there was actually a driver list that was inside the framework. And this can send multiple references to Kiehl's suit only or Kiehl's suit removed driver after installation. We found that these actually refer to Kiehl's suit loader drivers. Uh but after installation and infection of the machine we couldn't actually find any trace of them ever being used. So although they were inside the framework we couldn't find any trace of them on what we were looking at. So something that could be looked at later but we we couldn't find anything. So removal and neutering of a Kiehl's suit basically requires the understanding of how uh Kiehl's suit operates. And it focuses basically on that it always refers to this encrypted registry database I explained. So the boot pack itself will load the Kiehl's suit modules from the registry database. The running Kiehl's suit instances refer to the database. The pill chief instance when it tries to enact Kiehl's suit um actions has to refer to the database so as you notice everything refers to the database. So if you know where the registry database is and you remove it you just you destroy it. You basically neuter Kiehl's suit and all of its functionality. Now that breaks down to knowing where Kiehl's suit is. So um that that requires obviously a bit more searching of the two lists. And obviously if we find the two lists we can find all of it. Um if not uh the list that we provided we have done a research paper and the two lists that we found of the two halves and basically any combination you can find it's an easy sweep to do across an estate. So now that I've gone over well how to find Kiehl's suit and how to remove it. The what's more interesting and what's very important is how the SOTI there SOTI boot pack SOTI time boot pack operator which is their advanced boot loader works. Um and for that I'm going to hand over to Lacey who did the research. So thinking about all those like complex frameworks that we just saw for defense evasion um it will probably be pointless if you do not implement a persisting module which the attackers could connect back to should a petrochip connection be dropped. Um installing a persistence mechanism actually means that if the system is patched from the exploit that is present in fast sponge the attacker will still be able to compromise the system at any time they want. So how do we find out the different methods of persistence in Kiehl's suit? Um we can type the command Kiehl's survey in the Dennis Brits terminal. This figure here shows that there's three types of persistence methods that you can do with Kiehl's suit. And the very first one is driver. Then you have SOTI which stands for solar time. And then you have Juvie which stands for just visiting. So one cool thing about this command is that it will tell you whether it is compatible with your victim host. Um for example driver is outdated because of code signing policies that Windows implemented. And just visiting is also outdated because it is built for Windows Vista. So the only compatible method that we are left with is actually solar time. But what exactly is solar time? So I was really curious and I wanted to find out whether there are any information available online about this elusive method. Um and I found out to be as safe as possible equation group went really low level as they can which is infecting the firmware. So according to a report made by Kasper ski, solar time was first term by them as gray fish. It inserts appeal into the firmware which hijacks the boot sequence of the operating system. And then it gains complete control to install a virtual file system in the registry of the hard drive. And this is the gray fish architecture presented by Kasper ski. So in an infected volume boot record, an encrypted container file is loaded. The container file will then load a kernel mode orchestrator which downloads the user mode part from registry before starting the payloads. And so what we are going to do is to focus on the left box portion of the diagram. But what exactly is this encrypted container file that is loaded in the volume boot record? To check whether to check which is the container file being loaded, you can run the check salty python script in the Dennis Brits terminal and it will tell you the solar time container present in the disk. This is the only file that is searchable through the file system on disk. And this container file is stored as a true type font file and will be the very first file loaded by windows even prior to kernel initialization. So since solar time affects the volume boot record, it is considered as a boot kit. And before analyzing boot kits I would like to go through a little bit on the windows boot process. So the first step is during power on the bios boot code begins with basic system initialization for example simplified input output interface. The bios then loads the master boot record which finds the active partition and loads the volume boot record. The volume boot record contains partition layout information in a data structure called the bios parameter block. This block describes the physical layout of the data storage volume for example is the NTFS or the FAT file system was the number of sectors per cluster etc. The volume boot record then passes control to the initial program loader which is responsible for parsing the file system. It then loads the boot manager which manages the boot process until the user chooses a boot option before loading wingload.exe which is responsible for starting the kernel. So after all this reading up and discovering our bootkits and grayfish how does solar time actually work in relation to this boot process. So the very first change we notice is that solar time disables error reporting in the volume boot record. Looking at the volume boot record instead of a hot instruction solar time change it into infinite loop. Operational errors are standardly displayed by hitting a hot command stopping function so examples could be a missing or compressed boot manager. And solar time changes this so even if an operational error occurs no error reporting actually happens. So this prevents alerts or cause of investigation into the cause of a boot failure. And the second disparity between a normal boot process and solar time infected boot is that it relocates the IPL. And right before passing control to the IPL solar time replaces multiple instructions with not bytes and overrides the jump destination. And so the reason for overriding this destination is that solar time hides a lot of data at 7E7A. So this forces solar time to use an alternate location to launch the IPL from within the volume boot record. So this is a sample from an infected boot. You can see that the address 7E7A contains lots of random bytes and so it turns out that these bytes store the file reference and encryption key that are used later on to load and decrypt the file. So if the control pass to the IPL, solar time then starts to locate and load the container file. And to do that solar time uses many of the in-built loading functions already in a normal boot by inserting an ECX flag. So this way solar time can control when to load its malicious file without affecting the normal IPL process. So reusing standard boot code is more efficient because solar time will not have to rewrite everything which would probably introduce a lot more instability in the system. As the IPL is responsible for parsing the NTFS file system, I'll squeeze in a little information on that. So NTFS is the file system of Windows and everything on an NTFS volume is a file. And one of the special file you have in NTFS is object ID which contains unique IDs given to every file. So the attributes of object ID are the five shown here at the different offsets. And I would like to draw your attention to the third attribute which is index root. Index root is the root node and contains a list of all index entries of the object IDs. So a typical index entry structure in the index root of the object ID file is called the old index. And solar time identifies its container file by comparing the GUID object ID value in the old index with the object ID stored at address 7E7A. And once the right old entry is found, the MFT file reference can be fetched to load the file record. So this diagram shows how solar time actually hijacks a normal operation of the IPL and loads its container file. And in the malicious flow, solar time passes the object ID index root depending on the ECX register. This object ID file is not usually loaded or needed in the IPL section of a normal boot process. And if the ECX register is set, a standard load will occur. If not, it will load the index root of the object ID file, locates the index entry of the container file, and then load the file record before loading the file data. So on the left shows the file record of the boot pack loaded with the name David BydogtTF. And on the right are the contents of the file being loaded to address 600,000. And so after loading the true type font file, SOTI decrypts the malware using the encryption key hidden under 7E7A. After decryption of the malware, solar time then proceeds on to calculate a CRC32 hash to verify the file integrity. So how can we detect and remediate solar time? Since Qsuit can only use solar time to install on modern operating systems that are still using the legacy boot, detecting solar time will be a solution to detecting all Qsuit instances. Installation of solar time can be determined in two ways. First, you can use the checked solar time Python script, but this is inconvenient because you probably need to pawn your own machine to check it. Examination of the script did reveal things that are helpful, which are the various names the kernel driver container could be stored under. So in this case, the name David BydogtTF corresponded to the file that we found in previous slides. And the second way of detection is to check the volume boot record itself. As mentioned, solar time outputs the VBR, changing the jump address when transferring control to the IPL. And in doing so, it inputs two knob commands at 267 and 268 bytes of the VBR. So this alteration can be searched by using Python. We modified the open source code PyMBR written by Hamtus. And in our modified version, we find the first section of the NBR to find the start of the VBR. We then check the data in the VBR at bytes 267 and 268 for the hex value 90, which is code for knob. And if the knob value in place is in place, we can confirm that the VBR has been modified. So solar time is really hard to prevent because it infects the firmware of the drive. So unless manufacturer signs the firmware, modifications in the firmware would go unnoticed. However, since solar time does only affect the legacy boot systems opting for UEFI secure boot, what prevents solar time from working? Okay, so this is supposed to be a talk given by Francisco Donoso, but internet is definitely not working now. But this is what inspired our research. And this is a book that is also fantastic for my research. So do check them out if you have time. And yep, we are done.