Welcome everybody to APT's Love PowerShell and Why You Should Too. I'm Anthony. I'm here with Jake. We're going to be going over some of the interesting things that APTs do for PowerShell. And here we go. So once again, I'm Anthony. I go by coin. That's my handle. I got a master's in electrical engineering, same with my bachelor's. Some interesting things about me. I'm a lock picking hobbyist. You followed some of my work. I did some Bluetooth lock picking hacks over the years, as well as some wireless stuff. And then a lot of my focus recently has been building up Empire and Starkiller. And then I got Jake here as well. Yeah, hey guys. I've got... my background's a BS in astronautical engineering and I have an MBA. I actually ended up getting into cybersecurity while I was in the Air Force because I showed up at a new unit and they'd been told they had to have a cybersecurity person and I was voluntold that I was the new person. So after that, I ended up as a... doing some cyber testing for fighter aircraft for the Air Force. Then went on to a red team where I was a red team lead for about a year and a half, two years. And then I got out of the Air Force and now I'm currently focused on embedded systems security. And I'm kind of our PowerShell obfuscation expert for BC security. So I spend a lot of time on that too. So we get told this all the time and ask this question, you know, aren't PowerShell attacks dead? You know, offensive PowerShell's dead. Why don't you just move to C-sharp? Script logging to, you know, makes PowerShell attack completely impossible. You know, all these sort of things everybody always brings up. And we're constantly being told this, you know, why use PowerShell? Isn't it dead? Yeah. And just kind of a fun story about that bottom line about AMSI is going to catch offensive scripts is we gave a webinar back in February that was actually a workshop we taught at DEF CON last year. We had a Microsoft security guy show up with and gave us the challenge a couple of days beforehand that he was curious to see if we'd actually be able to get AMSI or passed AMSI on a fully patched machine. Whether it was intentional or not, they actually rolled out some updates to AMSI like the day before we started our course. Like they added some additional detections when you're using like invoke expression and that kind of stuff that did throw a little bit of a loop. But by the end of the class, the Microsoft guy was a little bit blown away by the fact that we could still get default Empire payloads past fully patched AMSI stuff just using obfuscation and some of the tactics and techniques we'll talk about a little more going forward. So obviously PowerShell is really, really dead. It can't be used for offensive PowerShell anymore. So this is just a quick poll that you can just go into Google and look over the last couple of months. What you can see is just APTs and threats are using offensive PowerShell pretty regularly for all types of things, not only just for breaches, but for ransomware attacks, for lateral movements, gaining initial access. It's being used for all sorts of things. Okay, so just a quick primer in case everyone's not fully aware of PowerShell. Why PowerShell and how it became a popular offensive tool in the first place is that it gives us full .NET access to Windows, which is kind of really the underlying architecture for being able to do a ton of lower level stuff in Windows. It gives us direct access to the Win32 API, which also gives us low level access to operating system functions. We can operate entirely out of memory, for the most part, and then installed by default in Windows. And admins typically leave it enabled because it is a huge efficiency enabler in terms of their jobs and that kind of stuff. And, you know, the theme of the day is going to be why PowerShell is still relevant and how we still see it being used by red teams. So this is just another tweet on the side about how Microsoft and red teams talk about PowerShell being totally played out. Meanwhile, APTs and criminal groups are using PowerShell every day. They might not be using it for the full attack chain, but almost every APT is using PowerShell in some way, shape or form during a breach. So now we're just going to do a quick timeline of PowerShell, like when it was released, when offensive tooling started coming out and when defenses were incorporated into it. So PowerShell version 1 came out in 2006. It was released for XP, Service Pack 2, Server 2003, and Vista. When it was first released, it didn't have a ton of capability. It was kind of more of a novelty thing. And PowerShell version 2 is when we really saw it start getting widely adopted. It was fully integrated into Windows 7 and Server 2008. It introduced a bunch of new features such as PowerShell remoting and background jobs. PowerShell version 2 was like when we saw the real adoption by sysadmins and that kind of stuff, to the point that many there are sysadmin tools that you will encounter on live networks still that run in PowerShell version 2 because that is what they were written in and they don't want to take the time to go port it to a different version. And so you'll find networks that still have PowerShell version 2 enabled because they want to be able to use their automation scripts. And so version 2 and version 5 that we'll talk about in a second are kind of the big delineators of what's going on in PowerShell version 2. If we can run in version 2, that's where we want to be as offensive people. And version 5 is where we got the full Gucci set of defenses. It had a few protections, but it had essentially no protections. And then Trusted Security, David Kennedy and Josh Kelly gave their PowerShell it's time to own talk in 2010. And that was when we saw the beginning of the wave of offensive use of PowerShell. They were really kind of the initialization of the movement for offensive PowerShell tooling was their talk that they gave in 2010. So that's when we started seeing people begin to adopt things. PowerShell version 3 came out two years later in 2012. It introduced module logging, which we will talk about that more. I actually think it's one of the more powerful logging capabilities in PowerShell, and it was introduced all the way back in version 3. But PowerSploit was first published in 2012. A lot of people don't realize just how old PowerSploit is at this point. And then Metasploit also introduced its execute PowerShell capability in 2012. And 2013, PowerShell version 4 came out. This was where rudimentary strip block logging was introduced. It's more akin to what PowerShell version 5 referred to as transcription logging. So it did do some script block logging, but it's not nearly as powerful as the one introduced in version 5. And then 2014 is where we start seeing like the just overwhelming wave of offensive tooling and everyone adopting it. PowerView gets published, PowerUp gets published, CobaltStrike incorporates PowerShell execution into its tooling, and that just kind of starts the major wave of offensive PowerShell. PowerShell version 5 was introduced in 2015 slash 2016. It's got two dates because it was officially released in 2015, but there was a major bug in it that required it to be re-released in 2016. So it sort of has two release dates. But in 2015, PowerShell hurts the blue team was published and it was a article published by Microsoft that introduced this whole host of PowerShell defenses to combat the offensive movement of malware through PowerShell. So it introduced what they call deep script block logging, transcription logging, talks about module logging some more, and then the big game changer was the introduction of AMSI, which we'll go to in more depth in a second. That's also where PowerShell Empire was released as well as PowerPick. So now that we've kind of gone through that timeline, we can see who's still using it today because we hear about people moving to C-sharp and that PowerShell, as we said, played out and that kind of stuff. But these are all the APTs that are currently still using PowerShell. So pretty much everyone. That's not to say that they're operating entirely in PowerShell, but they're using it in some way, shape or form. That's how we'll just said like just about every threat and every APT is using PowerShell in some sort of capacity. And when you're trying to go out as a red team and try to emulate those threats, you want to know what they're doing. I know we're focusing on a lot of PowerShell during this talk, but there are other tactics, techniques, procedures or TTPs that people use. So be able to do that research. You want to be able to research what those behaviors of the adversary is doing and kind of build that cyber threat intelligence based on whatever the threat is that we're looking at. And this is important because this is something that, you know, a lot of industry is going to be using, governments do, as well as some of the open source community. You can use things like FireEye if you want to pay for some of that threat intelligence info. Otherwise, another option is always go on to MITRE's page for the attack framework. And you can do some research there to see, you know, what techniques certain APTs are using, maybe get some more info if they're using PowerShell specifically, and then see, you know, what sort of lateral movements or what sort of privilege escalation techniques they're leveraging when they're focusing on PowerShell. So just a nice thing to mention, because we're doing a lot of, we're talking a lot about APTs and being able to go back and kind of do some more research with them is pretty important. So when you start doing some of that research on APTs, you'll find that they're using PowerShell for a lot of different reasons. Obviously, command and control is a big one. There's a lot of different C2 frameworks out there that are being used. You'll see some of the APTs using things like Empire or other C2 frameworks to kind of control whatever they're doing for their implants. PowerShell can be leveraged for their DLL hijacking. It can be used for key logging. One of the really big ones that's used for is lateral movement and privilege escalation. Lateral movement specifically for the PS exec, you have PS remoting, you have WIME. All those things are all leveraged using PowerShell. And then privilege escalation specifically for INVE. So really everybody's still using a lot of offensive PowerShell. These are some numbers that we pulled pretty recently. Most of these are within the last couple of months when these reports were published. Carbon Black put out that about 90% of target attacks are using PowerShell. So it's a very big significant number. As well as McAfee for this last quarter put out there was a 689% increase in target attacks using PowerShell. So not only is PowerShell still being used a lot, its use is increasing significantly by each quarter and every year. And the last one, CrowdStrike's most recent report said about 50% to 70% of target attacks, they observed PowerShell. Pretty wide range when you're talking about how many attacks are actually using PowerShell out there. One of the examples that we're going to talk through is APT33. If you do some research out there, you can see that they rely pretty significantly on PowerShell to be able to do their stuff. They are a suspected Iranian threat group. So they are state sponsored. And they're really going to be focusing on aerospace and energy industries. So a lot of defense contractors is what they're really aiming for. So trying to hurt the industrial base of a country when it comes to defense is really what their target is. And they're typically employing things like Empire, PowerSploit, and Mimikatz, focusing mostly on the PowerShell side of things. They have been seen to use things like CobaltStrike and other things for some of their beacons, but they're trying to stick mostly with a lot of the open source stuff that's put out there. So this is just an excerpt of one of their malicious files that they use that FireEye did a report on a couple of months ago. And what they did was they used a malicious HTA file, which is an HTML executable. And what that does, it has just a regular HTML on the top part that may point to a certain person. In this case, it was this aircraft company. And then after all that HTML, they embed a script. So the script that they're running launches a PowerShell hidden window with a base64 encoded payload attached to that. And this launching method is actually very similar to how Empire does a lot of their things. So you're talking about emulating what the threat does. Empire emulates this threat pretty well, especially with the HTA file. Next is WastedLocker ransomware. This has been pretty popular in the news recently. This is from the EvilCorp group or Drydex. And what this does is it leverages a few different things to be able to launch the ransomware. First, it leverages a CobaltStrikeBeacon and PowerView, kind of get that initial foothold. And it contains both PowerShell, JavaScript, and .NET. So it's really leveraging everything when you look at how they go about launching this ransomware. And once they get that initial access with that CobaltStrikeBeacon, what they're going to do is they're going to run PsExec, which is going to launch PowerShell and run the WastedLocker ransomware. And once that ransomware is in place, that's really where they're going to make their money. They're going to lock down companies, individuals, whatever they can, their machines. They're going to put out a Bitcoin address or whatever other cryptocurrency they want to get paid in. And they're going to then hide those keys until you guys pay the fees. And they've been very, very successful with this. The numbers being reported at the moment is they've made at least $100 million using this sort of ransomware. So it's a very profitable business for a threat to be able to use. So being able to see how they do it and then emulate what parts we can is very, very important. Yeah, and then this comes from a case study that Microsoft did on a breach that happened to Nepone Telegraph and Telephone. They actually didn't have enough indicators of compromise or enough access to the NTT findings to do a direct analysis of all the techniques themselves. But what they were able to do was build a lab that restructured the representative architecture of NTT and then kind of theorized how they would do it, which ended up using a decent amount of PowerShell. And we just included this one because we thought it was highly representative of like these major corporations that we're seeing being attacked now because they use a hybrid infrastructure of on-premise servers as well as cloud servers and then Active Directory and just it's a very complex attack surface. They still ended up utilizing PowerShell through several of the steps to pivot through. So they used phishing to get an initial foothold. Once they had that initial foothold, they were able to gain domain information. Then they scraped social media in addition to add to the information they had from the domain information to start building like what people's emails might look like or their usernames and that kind of stuff. Once they did that, they started password spraying to get access to the cloud server, which they designated server B as part of their case study. Once they got access to server B, we start seeing them use a lot more PowerShell because PowerShell in the cloud is still very effective. And what they ended up doing was building a brute force attack on user accounts on server A because server A was a privileged production server. And what they were looking for was accounts that had both cloud privileges as well as local privileges because those users don't always overlap. So they first use PowerShell to start trying to identify users that had had synced accounts between the local network on server A as well as the cloud network that was in server B. Then they were able to brute force those accounts to start trying to get access to server A. Once they got onto server A, they were able to extract passwords from LSAS and remote sessions to get remote access to the Active Directory server. Once the Active Directory server was compromised, they added a backdoor into it to maintain persistence. And if you look at these images, those are just showing some of the PowerShell they used. And again, we're just showing how this was used to target a major international telecommunications company that had servers in multiple locations as well as cloud and local-based. One of the last ones for our case studies that we just want to show some PowerShell usage in the wild is one that we were contacted about a couple of months ago. There was a very large international hotel chain that reached out to us and said that they detected some malicious activity on their network and they were downloading payloads from our GitHub specifically. And what was going on here was they were getting an initial foothold inside the network. They were trying to stay as lean as possible. They were going out through the web, reaching out to our GitHub, which we hosted Empire. They went specifically to one module, which was our Invoke Mimikatz module. Since we keep that pretty up to date, they were downloading that right onto the network so they can run it locally. And that way they could run Invoke Mimikatz completely locally. This technique of downloading things from GitHub and other destinations is a pretty popular technique among APTs. And you can find it in the CrowdStrike report for 2020. It's pretty widely used. One of the interesting traits about this though that really stood out to us was the fact that they were running things completely unobfuscated. They were running it just without any obfuscation or if they had any evasion at all, it was very, very basic techniques. Normally, you wouldn't see this from a threat, but it actually had some really interesting results from it. First, the defenders on this network waived it off initially because they thought it was the internal red team practicing. So since a lot of those weird obfuscation techniques really make things stand out in the logs, their blue team didn't think anything of it because they just thought it was the red team testing internally. So being unobfuscated in this case actually worked to their advantage. They still ended up getting caught eventually, but it really was a benefit for them. Yeah. And just to add to that, the hotel chain did stop them from compromising anything before they lost any user data or anything like that. It was just initially, they thought they waived it off the activity. So the attackers did have some extra time while they were trying to deconflict that it actually wasn't the red team that they thought it was. Now that we've talked about all those case studies, we've mentioned some of these logging techniques and that kind of stuff that have created, when fully implemented, created an environment that's actually fairly difficult to use PowerShell in. If you use the full capabilities of strip block logging and module logging and AMSI combined with an EDR, that does make PowerShell pretty hard to get through. But our point, especially we've specialized in working with smaller to medium-sized businesses, and you just don't see them using this fully. Maybe they do have strip block logging enabled or module logging enabled, but they're not ingesting it properly into their scene because it's producing so much data. And so, or they don't have good signature, they don't know how to build signatures that would flag on malicious data, but not on their admins. So it's not the protections that we often see it portrayed as in the offset community. They're just, oftentimes you see the limitations of real-world implementation don't meet what the full capability can be achieved in a lab. And then also just something else to note is that, you know, AMSI has already been incorporated into .NET. So C-Sharp now has to deal with AMSI and Microsoft is, you know, constantly innovating and looking at ways to start to improve the defense of .NET now that we're seeing a lot of people doing that. So the advantages that C-Sharp have today have already began shrinking from what PowerShell has and are, and will probably continue to shrink into the advantages that it has over PowerShell as Microsoft implements more and better defenses into .NET. So now we're going to talk about AMSI in a little more in-depth. We hear about it a lot, but often people don't really fully understand exactly how AMSI is working. So AMSI is the Windows Anti-Malware Scan Interface. I'm going to go ahead and read off the Microsoft definition for you guys. It's a versatile interface standard that allows your applications and services to integrate with any anti-malware product that's present on a machine. AMSI provides enhanced malware protection for your end users and their data applications and workloads. So that's great, but kind of what does it mean? And what that means is that AMSI, first of all, doesn't work with just PowerShell. It works with VBScript, it works with JScript, as well as other applications that we want to send information to. It's built to be kind of this all-purpose lower level layer that you can tell it has predefined interfaces that can then be connected to an antivirus. Traditionally that's Windows Defender, but also McAfee and others tie into AMSI and rely on its detection capabilities for seeing malicious things going on in memory. And it's also processing... the big advantage of AMSI is that it's processing the commands at as low a level as possible before it enters into the script engine. So a lot of obfuscation that is put in place is removed before AMSI even looks at it. And this is just a diagram of how that data flows through those layers. So as I said, it evaluates commands at runtime. So if you were to use XOR encoding or secure string or some of those other obfuscation techniques that you might see out there, that obfuscation has to be removed before it can go into the scripting engine because the scripting engine doesn't know how to translate a secure string or an XOR encoded string into commands that it knows how to read. So it helps us identify fileless threats. And as I mentioned previously as well, as of .NET 4.8, it is integrated into the common language runtime, which is what PowerShell and all these scripting languages are actually decompiled or compiled into the common language infrastructure that's ran in the common language runtime. So they actually all end up running in the same area. And now C Sharp also uses the common language runtime. And so AMSI has been integrated at that lower level to account for some of the other languages that it didn't initially account for. So AMSI is actually pretty powerful. And we'll talk... we've got a couple examples that we're going to go through here. One that Anthony will talk to more when we get to the obfuscation stuff. But this is just what a standard Empire implant looks like when you put everything in. And if we just make some changes on the structure of the code, it still goes through AMSI. Like it's still very, very heavily dependent on static signatures. So this is just our modified script. You know, we changed some variable names and changed some locations of where things were being done because some of the code was position independent. It just had to be ran before the end of the script. So we moved it around. And now it runs without issue. Well, this did run without issue. They are constantly updating signatures in this one. This specific implementation probably will not pass AMSI anymore. But when new AMSI signatures come out, it typically takes me about 30 minutes to an hour to be able to come up with a workaround for whatever they changed for the detections. It might be... it's worth us also pointing out that we get a lot of questions all the time since we do a lot of work on Empire of, you know, why don't you keep the signatures up to date constantly? So that way it's always avoiding AMSI and Microsoft and all the defenses that are out there. And it's really just a cat and mouse game at the end of the day. So if we go and update it, it's going to take them, you know, hours to get the new signatures updated. And then whatever all the work that we just did is now worthless. So for us, it's easy for us to easily make these changes and do it, but not publish it out there. So that's just something that we see a lot. And we get a lot of questions asked of just why we're not making these changes on the releasable stuff for Empire. And if you are interested in learning more about the obfuscation stuff, we do have like a YouTube video up on that goes like... it's about three and a half hours of how to bypass AMSI and avoid it. So there's plenty of information out there. So now we're going to talk about script block logging. It was first introduced in PowerShell version 4, but it was fairly rudimentary at that time. Version 5 introduced what Microsoft calls deep script block logging. What that means is that it follows the execution down through multiple levels, which we'll talk through in a second on these images. And then it's event ID 4104, if you go look at the PowerShell operational log in Event Viewer. During our demo, I'm going to go over a little more how you can find the Event Viewer and what's in those logs and how we can look at them and that kind of stuff. But for now, if you look over on the image on the left, the first six lines there are defining a function called super decrypt that is removing the XOR encryption of a string and then returning that string in Unicode. Now, if we go down to the next line, it's going to decrypt that string there, store it into a variable, and then they're going to use invoke expression to execute that decrypted string. And we won't see it on the transcription log, we just see what is entered into the command line. But if we go over and look at the script block logs on the right over here, we can see the first one where we defined our function. The next one down is you're running that decrypted equals super decrypt to run our function. Walk down to the next line, where you see invoke expression of the decrypted variable. And then this is where that kind of deep script block logging and following the things down becomes powerful for AMSI. After all of that, we see that what was actually executed from that encrypted string is that write host pwned. So that is like why AMSI is powerful, is even though we had this function that we didn't really know it was going on with like bytes and counter and all that stuff, and decrypting this XOR string that we couldn't see into, we still see what's executed by invoke expression at the end. And that's what makes AMSI power or script block logging powerful. But we'll talk about some ways that you can actually obfuscate the script block logging in a little bit later. So module logging, it was introduced in PowerShell version 3, and I think is the most powerful part of the PowerShell logging capabilities. It does have some issues in implementing and building proper signatures, because it does report each module individually. But it's nearly impossible to hit the log without being unobfuscated. I say nearly impossible because maybe someone knows a way of doing it, but I have never been able, I've never seen or been able to figure out a way where you can not hit this log unobfuscated. If you look over at that image on the right, that kind of setter block, the first line will say like command execution, or sorry, command invocation, new object, and it shows new object. That's telling us what module is being ran, which commandlet. And then the next line down, you know, says parameter binding. And then if you go all the way over to the right, it says value. And that is what is being passed to the commandlet. And that value is always unobfuscated from what I've seen. If someone knows of a way obfuscating this, I'd be really interested in hearing about it afterwards. But that's why it's so powerful, is the values being passed in as arguments for commandlets are always unobfuscated. But it produces a whole lot of alerts. FireEye went and did a study when some of this came out, and running invokeMimikatz, just that, nothing else going on on the network, running just invokeMimikatz produces 2,280 events, generating seven megabytes of logs from just running that one script. So as you can see, that generates a lot of data and a lot of events that we have to sort through to be able to build efficient signatures and not just have this data for after the fact. So PowerShell logging would make for a bad day for red teams if organizations actually use it properly. But unfortunately, we have a bunch of things that are in the operational world that are, you know, making that more difficult. You see alert fatigue, you know, administrators are using sketchy scripts. I've been to a Fortune 500 company where when we went and looked at the local logs on the machines, their EDR was interfacing with AMSI. And each individual machine was producing like 100 alerts every two or three hours because the admins had a script they were using for automation that was running every couple of hours to make sure all the baselines for everything was staying, but it was doing something sketchy that was triggering the EDR to say it was bad. And so basically they had all the alerts set to information only and the EDR wasn't doing anything to kill the PowerShell when it was being flagged as bad because the administrators didn't want their scripts being killed. And you now have your SOC dealing with just, you know, thousands of alerts every day that they know are not really alerts because it's just the admin guys. And, you know, the admin guys update their stuff so they don't necessarily have a good way of automatically knowing or automatically filtering out those admin scripts, although in an ideal world they would be able to do that. And then deep script block logging can result in multiple alerts for a single script execution. Again, FireEye was testing with invoke-mimikatz and it produced 116 events totaling five megabytes when you use just the standard script block logging settings. Script block logging actually has an additional setting that you can turn on that it has it record start and stop events for loading different modules and executing pieces of code and that kind of stuff. And when you enable that, your logs jump to 96,000 events totaling 50 megabytes of logs for running one script. And then on top of all of that, bypasses are still effective because things like script block log bypasses or AMSI bypasses that we'll talk about in a little bit are not considered as crossing the security boundary by Microsoft because it's all operating on its own process. And since it's the owner of that memory space for the process that it's working in, it's not breaking any boundaries because if it turns it off for itself, then there's no way to prevent it from doing that. So this is just a quick overview of kind of what Mandiant says. Should they recommend for doing logging? They say if you can to enable module logging, script block logging, and transcription. We didn't really talk about transcription because it's fairly straightforward. All it is, is recording what is written out on the command line. And it doesn't include... that's all it includes. It's just be... it's a replay or a text version of what was typed into... what you see as you're typing into the command line. And they say the unique data is recorded by each source. And then this is kind of the takeaway I like to point out to people when we... when everyone says like, oh, logging is like, you know, the end-all be-all for PowerShell. They say where log sizes cannot be significantly increased, only enable script block logging and transcription logging because it will cover most data. And module logging only buys you some. But as I talked about, we have some ways of obfuscating transcription and script block logging so that even if you do record that data without bypassing script block logging, you can't tell what's going on in the scripts. And then module logging is basically impossible to hit unobfuscated. So it provides much better insight, in my opinion, but does produce a whole bunch of data. And because events are individual, correlating them becomes harder. So now we're going to talk about why it's still really effective for red teams and APTs to still go after this stuff, you know, mitigating the mitigations. We'll go over a little bit of AMSI bypasses, some obfuscation, like standard obfuscation. What we refer to as keyword obfuscation, which is kind of doing some minimal obfuscation to bypass AMSI because heavily obfuscated scripts can be a flag in and of themselves. We'll talk a little bit about script block logging bypasses and then event tracing bypasses. Those will be primarily in the demo. So reflective bypass. It's the simplest bypass that currently works. It grabs the systemmanagement.automation.amsi.utils.dll. It grabs a reference to it and then changes a field that says AMSI init failed and sets it to true. So why this works is when they were incorporating AMSI into PowerShell, they decided that if there was an issue with AMSI starting up rather than just killing PowerShell, not allowing PowerShell to run if AMSI couldn't run, that it was better to basically fail safe and just have AMSI ignored by PowerShell so that the PowerShell tools could keep working. So when we're reflectively setting this field, we're saying that the initialization of AMSI failed. So just go ahead and return a clean finding regardless of what was actually done. And it doesn't even bother scanning the code. It just says there's something broken with AMSI. So we're just going to tell Defender that everything's fine in terms of malicious content because we don't know what's broken and we don't want to stop PowerShell from running. And then it's also just kind of cool because Matt Graber originally posted this in a tweet all the way back in 2016 and still works. So a more complicated bypass we can look at, and there's a bunch of different implementations floating around. This is one I wrote based off of Tal Lieberman's work that he published at BlackHat. Rostamaus has a very similar one implemented, as well as there's a few other places you can find ones that are based off of this off of this patching of the actual AMSI DOL in memory. So this is using some a C-sharp to export DOL functions to allow us to access some areas of memory. And then we are patching when AMSI goes to return the results, there's actually a numeric value that it measures to define your risk rate. And if it's over x amount, that's considered bad. If it's under x amount, then it's considered mostly good. And if it's a zero, it's considered good. Basically, you never see zero returned in real life. And you actually never see the different values with the actual value of your script rows, because when it returns the value, defaults it to one of those three. There's actually a couple others for policy implementation issues. But those are the three returns if it's just scanning your code without outside influence. And what this does is it patches it to always return that the code was good regardless of what the comparison finds of what the value actually came out from AMSI. It says just return a good value from the comparison and say that the script is fine. And so all of these work because AMSI is loaded as part of the memory space that our process is in, which means that we have unrestricted access to the memory space that we're in. We can modify it however we please. And so the reflective DLL tells AMSI to return a clean result prior to scanning it. And as I mentioned, the patched one tells it to return after it being scanned. So obfuscation, going in kind of a different direction with that, is taking that code that we've established and adding some more noise in there to kind of hide what we're doing. It's still very, very effective, but it does come with some costs. One of those being the complexity of your payload. Your payloads will become really, really complex and they'll add a lot of size to them because you're going to be running a bunch of different techniques. You may be encoding it on top of changing variable names and splitting things up. So you can easily exceed limits that are put in place by PowerShell on the size of a command. It also takes a lot of time to be able to encode these. So if you're running every command that's being sent across your C2 framework as obfuscated, there's going to be a delay there. Now that may not be a big deal to some people, but depending on what you're trying to emulate, that actually could be a big deal. Then, as Hubble talked about, some of the defenses that are in place, if they take all that obfuscation and they wait till the very end, they may be able to detect whatever you're trying to do at the very end because obfuscation helps you in breaking up signatures and dividing things up. So that way they might not be identified, but if they're waiting to the end to run their analysis, you may get caught. Here's just an example of some unobfuscated and obfuscated code for a launcher for Empire. The left one just shows the basic payload without any obfuscation in it. The right one has just the standard token all obfuscation set in place. And what it does, you can see here, it starts breaking things up. It starts encoding things. This right here actually won't get past AMSI, the way it's currently implemented, just because of the way token all does some of its things. I'm sure Hubble will want to chime in a little bit on that. But the important part, though, is really seeing how it actually encodes this and the big red flags that defenders would actually see if they saw this in their logs. Yes, so token all, the way it's implemented in invoke obfuscation, is a pseudo-randomized implementation of a bunch of various different obfuscation techniques. And it has kind of two issues. One, it's pseudo-random. At this point, invoke obfuscation has been out for a very long time. And all of the randomization, or all of the combinations for those six techniques that it has, are fairly well known at this point. And then there's also some issues with certain techniques interfere with each other if they're ran in the wrong order. So sometimes you run into issues with that in invoke obfuscation running token all, as it might run... you see some of the stuff where it's broken things up into a bunch of string numbers. And when it does that, it then can't search for commands to replace the name of the command, because that's already been broken up, so it can't find it. So some of these things work better if you run them in specific orders. And invoke obfuscation's token all doesn't always do that. So that's just some of the limitations on it. And just having those custom cocktails of different obfuscation techniques make a big difference. I know we have a couple that we keep for ourselves that seem to work almost all the time. So the obfuscation really does get you about 90% of the way there. Like I said, those custom cocktails that we have really do get us most of the way there. But there's some things that you just can't get rid of when you're obfuscating. And those are just like those common signatures that require you to restructure the code or eliminate certain keywords. One of the really good examples was something that we saw last year with the original Empire project. Prior to version 3, there was actually a mistake inside of the code where it double appended one of the headers. This allowed signatures to be based off of that issue, because it couldn't be obfuscated away. So any virus and AMSI and everything was detecting off of this specific mistake in the code. So just removing that and then rerunning the obfuscation with a slightly different technique allowed the payload to get through completely undetected. So really, that restructuring and making sure that those signatures are broken is really, really important. So now we're going to talk a little bit more about what we kind of call keyword aliasing. AMSI can search in memory for specific terms and that kind of stuff that are automatically flagged as bad or raise your threat level really high. And these can be triggered even when not ran directly by AMSI. For instance, if you run a PowerShell script as Base64 encoded and AMSI does not flag it as malicious, it still sees that as a very suspicious activity. So then it starts searching strings in memory, or Defender starts searching for strings in memory. And specifically, it'll actually do this even when AMSI has been disabled, because Defender is seeing that as an inherently suspicious activity and Defender goes and looks for it as well. So getting rid of these strings in memory becomes really key to getting our code through, especially in allowing us to not heavily obfuscate everything all the time, which increases our size and the amount of data we have to transfer and all that kind of stuff. Some of these strings to keep in mind are actually invokeMimikatz, invokeEmpire, powersploit. It's not in here, but another one that doesn't necessarily get you flagged as malicious but generates a warning-level event in your logs, which means that it thinks it's highly suspicious and would be a trigger for someone to potentially go look at, is if you're using an assembly and use .getField. GetField is, in and of itself, a string that gets triggered as a warning-level event and will go cause higher-level logs to be produced. Even if script block logging is off, that string will cause a script block log to be saved, even when script block logging is disabled. So if we change those terms, then we can make it really hard to detect us, because if we change all the references in our script, there is nothing to de-obfuscate it from. It just becomes that is the value that we are using. So in the example over on the right, we're changing InvokeMemeCats to QAD45 and InvokeEmpire to DLXZ9. This is how it's done in Empire now. On startup, it automatically makes entries to obfuscate those strings. If you really want to be even stealthier, instead of changing it to just kind of these random letters and numbers, because if you looked at a log, that would be kind of weird that someone's using a function name that's completely random, because what legitimate programmer would be using a completely random name? You could make these something like InvokeFileSearcher, InvokeOrganizer, so that it would look even less suspicious than just a random string. We don't do this to everything for a couple of reasons. You could do it, but it's time consuming to pick which values to alias. And then it also requires us to put in a lot of entries into the database, and that makes it just harder to track, because everything we want to alias has to be tracked individually. And we have to make sure it's being applied across all of our scripts, because if we had a reference in a script in one place and ran it outside of Empire, and it was looking for something that Empire had aliased, or we had aliased by hand, and those don't match anymore, then your stuff's going to break. So there's just some complexity added in the aliasing. And then, as we mentioned, heavy obfuscation can be a flag in and of itself, so we want to minimally obfuscate where we can. So here's a new... I have not seen this on open source stuff yet that I've been working on that's pretty fun to play with. You can actually import to avoid script logs, as well as the transcription log as well. ImportAlias is the one I've been playing with the most. What happens is, when we import our aliases, for those that don't know, let me take a step back. Aliasing, in terms of PowerShell, allows us to set whatever function name we want for any commandlet. So the get command, or get printer, write host, any of those, we can say set alias and change it to print instead of get printer. And then, whenever you type in print into PowerShell, it knows that that is the same as doing get printer. You can then save those aliases using ExportAlias. And then, when you import alias, those terms and different names for your commandlets never get seen by the log. They just get imported into memory. You can now run the command with the name that you gave it, and on the script block log, that's all it sees. It'll see print instead of get printer. If you have module logging enabled, then it will still see the module you're using. And so, ImportAlias does not get you around module logs, although the module logs will not see the values in ImportAlias, which is kind of interesting. But as we said, it's basically impossible to avoid hitting the module logging initially. So, this is kind of what it looks like to change things up. On the right is if I want to do InvokeExpressionNewObjectSystem.net.webClient. That's what it would look like. That's what it would look like in the logs. Instead, to run that, I went and did some aliasing by hand. And we can embed further commands into the alias description. And if you look at the import.alias.csv, that imported all of my alias commands. Now I run this completely nonsensical command to someone looking at it that says I parentheses ca.description. And then that caused another execution that was bcb.description. So, in this case, I was was InvokeExpression. And b was that new object. And then the description for new object was system.net.webClient. And so, I ended up achieving the same thing with this totally nonsensical script block log that there's no way for a defender to go figure out what that actually means. Because as soon as you close the PowerShell session, the aliasing is gone. It is not saved saved permanently anywhere. So, you have to import. If you want to use aliases consistently, you have to import them each time you start a new PowerShell session. That's why the function was built. So, as soon as we kill our PowerShell session, our aliasing is gone. And the key to what the script block log means is gone as well. Now we're going to go into demo where I'll talk a little bit about more the event viewer and how to look at the PowerShell logs, as well as show the script block log bypass and the event tracing bypass that is used by the disables module logging in conjunction with all the other PowerShell logging. First things first, how you get to the operational log for PowerShell is you're going to use event viewer. You're going to come down here and type in event viewer. You want to make sure you run it as an administrator. That just makes it easier to clear the logs when you're testing that kind of stuff. But you can't usually view it even as an unprivileged user. You just can't modify it. You'll then click on Microsoft, then Windows, then come down here to PowerShell, open PowerShell, and then click on operational. Right now I cleared the logs prior to starting this so that we can make it easier to see everything. So, if I go ahead and click on PowerShell and open it, it's actually just starting PowerShell generates some logs. As you can see here, we get these event IDs showing startup, as well as it looks like my computer was a little slow. So, if I refresh it again, we should get a few more. Yeah, there we go. So, you'll see this verbose prompt and script block logging that is just a default that always gets generated when PowerShell starts up and after each command. Then we'll see this strict mode that gets used throughout when you're running PowerShell. But as you can see, this one's 4104, which is our script block logging, and then we have 4103 is our module logging. If I go up and run just this right host test as our kind of test subject, we can come back over and refresh our logs, and we'll see a couple of new entries in here. As I said, prompt comes up after every execution. But if we go down here, we can see this right host test for our script block log in 4104. And then we can see this module logging where we get the command invocation for right host, as well as the value that was passed, which was our string of test. So, now we're going to go over here, now that we've seen that. And the first one we're going to talk about real quick is script block logging. This was published by Matt Graber. It's got a few modifications from his original one, but this comes from a default Empire implementation. All it's doing is it's creating a new dictionary that gets added to our cache group policy settings. We access that reflectively, and we're just telling it that script block logging has been turned off when it goes. So, when PowerShell goes to check if it's supposed to be recording, it sees that the value is set to zero, which means it's not supposed to be recording script block logging. We're able to do this because, just like the AMD bypass, this is all in our process memory. So, we have complete access to it. We can manipulate in essentially whatever way we want. So, if I go drop this in here, like so, and we hit enter, we will generate a bunch of new events because we haven't disabled it yet. So, all of that code that we just ran is going to hit our script block logging. And so, we go up here, and we can see that our script block was ran with all of our different values. Then we get our out default, which is the module when output is sent to the command line, and then some other ones. And since script block logging is using an assembly, that doesn't actually generate any module logging because it's obviously not a module. But now, if we go back up to here, and I do our write host test, we will still generate a new event because module logging is on, and we haven't bypassed that. But if you go look here, as you can see, the last script block log, that 4104, was our disabling a script block logging, and now all we have is module logging, which occurs here with our write host in our test string. So now, the other nice part about this is that only affects our local process. So, if I just close out PowerShell and clear our logs, we will reset everything. So we're going to go ahead and clear, and then when we go, if I open it again, we're now going to use a event tracing bypass that was published about the same time, actually, as the script block logging one. It just never really got a lot of traction. It's, I believe it's linked in our slides. If not, I have the link for everyone that I can share. And all we're doing is it's very similar to that script block logging bypass, where we're getting access to a table that PowerShell is checking to see what it's supposed to be doing for logging. But instead, we're disabling event tracing, which happens at a lower level. This event tracing actually disables our module logging as well. So we run this, and we go look at our logs. And we'll see that we get a warning level event. This is because of some of the strings that we mentioned during the briefing, like the get field string, as well as some of these non-public static and those kinds of things will automatically generate a warning level event, which means this would actually produce a log even if script block logging wasn't explicitly enabled. So we ran this, but as you can see, we don't have any of those standard, like the prompt logging or this out default that's normally there. And if we go run that right host test again, we can see that we have had produced no logs. So we still have viable ways of totally disabling PowerShell logging. And like I said, there are ways to get this down, so it won't produce a warning level event. And then the last thing I was going to show you guys real quick is just that import alias thing we talked about. I was just going to show it to you real time. So we'll go ahead and clear the log. Open PowerShell back up again. We're just going to go ahead and import our alias.csv. I'm going to go ahead and run this nonsensical looking thing. As we can see, it gives us an output that a new web request object was created. So now when we go look at our logging, we can see a couple of different script block logs were called. So I called this ICA.description initially. And this is where we can see that it's still hitting our module logging. Even the script block logging can't see it. It appears that C is aliased to get command, as we can see here. I'm looking through that. But as you can also see, it's a little hard to correlate exactly what's going on and figure out what called this module without some in-depth analysis of what's going on. So we have this value A that gets passed to it. Then we see it execute this bcb.description, which again is a git command. And then we also see that we're executing a new object that was being passed a system.net web client. And so that just shows you module logging is kind of effective at bypassing this import aliasing thing. But the import aliasing totally obfuscates logs in a way that you can't really undo it. And the other nice part is when you import alias, the whole reason that you can import and export aliases is that they are not persistent between sessions. So when we close out PowerShell, all of our aliasing key is gone, so they can't go look it up. So it's just another level of obfuscation. And it also makes it really hard for Amzie to see what's going on. So that's just something kind of fun to play with. But that's all I got. So I'll toss it back over to Anthony. And we should have just a little bit of time left. Thanks for having us at the Red Team Village. We're going to be in the channel for a little bit to answer any questions.