1 00:00:00,000 --> 00:00:04,100 Welcome everybody to APT's Love PowerShell and Why You Should Too. 2 00:00:04,100 --> 00:00:04,920 I'm Anthony. 3 00:00:04,920 --> 00:00:06,400 I'm here with Jake. 4 00:00:06,440 --> 00:00:10,820 We're going to be going over some of the interesting things that APTs do for PowerShell. 5 00:00:10,940 --> 00:00:11,880 And here we go. 6 00:00:12,560 --> 00:00:14,500 So once again, I'm Anthony. 7 00:00:14,500 --> 00:00:15,460 I go by coin. 8 00:00:15,460 --> 00:00:16,520 That's my handle. 9 00:00:16,680 --> 00:00:20,460 I got a master's in electrical engineering, same with my bachelor's. 10 00:00:20,460 --> 00:00:21,760 Some interesting things about me. 11 00:00:21,760 --> 00:00:23,340 I'm a lock picking hobbyist. 12 00:00:23,340 --> 00:00:24,300 You followed some of my work. 13 00:00:24,300 --> 00:00:29,480 I did some Bluetooth lock picking hacks over the years, as well as some wireless stuff. 14 00:00:29,660 --> 00:00:33,760 And then a lot of my focus recently has been building up Empire and Starkiller. 15 00:00:33,760 --> 00:00:35,600 And then I got Jake here as well. 16 00:00:35,980 --> 00:00:37,120 Yeah, hey guys. 17 00:00:37,120 --> 00:00:41,640 I've got... my background's a BS in astronautical engineering and I have an MBA. 18 00:00:41,880 --> 00:00:52,840 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. 19 00:00:53,300 --> 00:01:00,840 So after that, I ended up as a... doing some cyber testing for fighter aircraft for the Air Force. 20 00:01:00,980 --> 00:01:06,520 Then went on to a red team where I was a red team lead for about a year and a half, two years. 21 00:01:06,520 --> 00:01:12,780 And then I got out of the Air Force and now I'm currently focused on embedded systems security. 22 00:01:13,200 --> 00:01:17,760 And I'm kind of our PowerShell obfuscation expert for BC security. 23 00:01:17,760 --> 00:01:19,520 So I spend a lot of time on that too. 24 00:01:20,060 --> 00:01:24,480 So we get told this all the time and ask this question, you know, aren't PowerShell attacks dead? 25 00:01:24,480 --> 00:01:26,600 You know, offensive PowerShell's dead. 26 00:01:26,600 --> 00:01:28,500 Why don't you just move to C-sharp? 27 00:01:28,520 --> 00:01:33,260 Script logging to, you know, makes PowerShell attack completely impossible. 28 00:01:33,380 --> 00:01:36,240 You know, all these sort of things everybody always brings up. 29 00:01:36,240 --> 00:01:40,400 And we're constantly being told this, you know, why use PowerShell? 30 00:01:40,400 --> 00:01:41,420 Isn't it dead? 31 00:01:41,780 --> 00:01:42,260 Yeah. 32 00:01:42,260 --> 00:01:55,140 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. 33 00:01:55,140 --> 00:02:08,940 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. 34 00:02:08,940 --> 00:02:18,080 Whether it was intentional or not, they actually rolled out some updates to AMSI like the day before we started our course. 35 00:02:18,080 --> 00:02:24,240 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. 36 00:02:24,240 --> 00:02:44,200 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. 37 00:02:45,040 --> 00:02:48,420 So obviously PowerShell is really, really dead. 38 00:02:48,420 --> 00:02:53,080 It can't be used for offensive PowerShell anymore. 39 00:02:53,100 --> 00:02:57,700 So this is just a quick poll that you can just go into Google and look over the last couple of months. 40 00:02:57,900 --> 00:03:11,580 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. 41 00:03:11,580 --> 00:03:13,760 It's being used for all sorts of things. 42 00:03:15,320 --> 00:03:21,420 Okay, so just a quick primer in case everyone's not fully aware of PowerShell. 43 00:03:21,420 --> 00:03:36,280 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. 44 00:03:36,280 --> 00:03:44,000 It gives us direct access to the Win32 API, which also gives us low level access to operating system functions. 45 00:03:44,000 --> 00:03:50,840 We can operate entirely out of memory, for the most part, and then installed by default in Windows. 46 00:03:50,840 --> 00:03:59,240 And admins typically leave it enabled because it is a huge efficiency enabler in terms of their jobs and that kind of stuff. 47 00:03:59,460 --> 00:04:06,400 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. 48 00:04:06,440 --> 00:04:13,520 So this is just another tweet on the side about how Microsoft and red teams talk about PowerShell being totally played out. 49 00:04:13,520 --> 00:04:19,000 Meanwhile, APTs and criminal groups are using PowerShell every day. 50 00:04:19,000 --> 00:04:27,840 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. 51 00:04:28,660 --> 00:04:39,260 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. 52 00:04:39,260 --> 00:04:42,240 So PowerShell version 1 came out in 2006. 53 00:04:42,240 --> 00:04:48,360 It was released for XP, Service Pack 2, Server 2003, and Vista. 54 00:04:48,380 --> 00:04:51,620 When it was first released, it didn't have a ton of capability. 55 00:04:51,620 --> 00:04:54,600 It was kind of more of a novelty thing. 56 00:04:55,320 --> 00:05:00,520 And PowerShell version 2 is when we really saw it start getting widely adopted. 57 00:05:00,780 --> 00:05:04,420 It was fully integrated into Windows 7 and Server 2008. 58 00:05:04,640 --> 00:05:09,820 It introduced a bunch of new features such as PowerShell remoting and background jobs. 59 00:05:09,820 --> 00:05:32,960 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. 60 00:05:33,100 --> 00:05:41,120 And so you'll find networks that still have PowerShell version 2 enabled because they want to be able to use their automation scripts. 61 00:05:41,300 --> 00:05:51,140 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. 62 00:05:51,140 --> 00:05:54,580 If we can run in version 2, that's where we want to be as offensive people. 63 00:05:54,620 --> 00:05:58,340 And version 5 is where we got the full Gucci set of defenses. 64 00:05:58,340 --> 00:06:03,300 It had a few protections, but it had essentially no protections. 65 00:06:03,300 --> 00:06:11,940 And then Trusted Security, David Kennedy and Josh Kelly gave their PowerShell it's time to own talk in 2010. 66 00:06:11,940 --> 00:06:19,380 And that was when we saw the beginning of the wave of offensive use of PowerShell. 67 00:06:19,420 --> 00:06:28,360 They were really kind of the initialization of the movement for offensive PowerShell tooling was their talk that they gave in 2010. 68 00:06:28,360 --> 00:06:31,360 So that's when we started seeing people begin to adopt things. 69 00:06:32,800 --> 00:06:36,540 PowerShell version 3 came out two years later in 2012. 70 00:06:36,540 --> 00:06:40,240 It introduced module logging, which we will talk about that more. 71 00:06:40,240 --> 00:06:48,800 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. 72 00:06:48,900 --> 00:06:52,500 But PowerSploit was first published in 2012. 73 00:06:52,500 --> 00:06:56,000 A lot of people don't realize just how old PowerSploit is at this point. 74 00:06:56,000 --> 00:07:02,600 And then Metasploit also introduced its execute PowerShell capability in 2012. 75 00:07:03,040 --> 00:07:06,820 And 2013, PowerShell version 4 came out. 76 00:07:06,820 --> 00:07:09,960 This was where rudimentary strip block logging was introduced. 77 00:07:09,960 --> 00:07:17,000 It's more akin to what PowerShell version 5 referred to as transcription logging. 78 00:07:17,000 --> 00:07:24,260 So it did do some script block logging, but it's not nearly as powerful as the one introduced in version 5. 79 00:07:24,460 --> 00:07:34,500 And then 2014 is where we start seeing like the just overwhelming wave of offensive tooling and everyone adopting it. 80 00:07:34,500 --> 00:07:46,480 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. 81 00:07:47,000 --> 00:07:51,020 PowerShell version 5 was introduced in 2015 slash 2016. 82 00:07:51,020 --> 00:07:59,320 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. 83 00:07:59,320 --> 00:08:02,160 So it sort of has two release dates. 84 00:08:02,380 --> 00:08:20,340 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. 85 00:08:20,340 --> 00:08:34,940 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. 86 00:08:35,020 --> 00:08:39,680 That's also where PowerShell Empire was released as well as PowerPick. 87 00:08:39,680 --> 00:08:56,820 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. 88 00:08:57,120 --> 00:09:01,060 But these are all the APTs that are currently still using PowerShell. 89 00:09:01,060 --> 00:09:02,760 So pretty much everyone. 90 00:09:03,720 --> 00:09:09,760 That's not to say that they're operating entirely in PowerShell, but they're using it in some way, shape or form. 91 00:09:14,720 --> 00:09:21,080 That's how we'll just said like just about every threat and every APT is using PowerShell in some sort of capacity. 92 00:09:21,140 --> 00:09:25,880 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. 93 00:09:25,880 --> 00:09:33,180 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. 94 00:09:33,460 --> 00:09:35,380 So be able to do that research. 95 00:09:35,500 --> 00:09:44,520 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. 96 00:09:44,780 --> 00:09:52,380 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. 97 00:09:52,680 --> 00:09:57,700 You can use things like FireEye if you want to pay for some of that threat intelligence info. 98 00:09:57,700 --> 00:10:02,540 Otherwise, another option is always go on to MITRE's page for the attack framework. 99 00:10:02,540 --> 00:10:18,540 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. 100 00:10:18,540 --> 00:10:26,940 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. 101 00:10:27,340 --> 00:10:37,240 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. 102 00:10:37,880 --> 00:10:40,200 Obviously, command and control is a big one. 103 00:10:40,200 --> 00:10:43,460 There's a lot of different C2 frameworks out there that are being used. 104 00:10:43,840 --> 00:10:53,180 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. 105 00:10:53,360 --> 00:10:55,900 PowerShell can be leveraged for their DLL hijacking. 106 00:10:55,900 --> 00:10:57,660 It can be used for key logging. 107 00:10:58,020 --> 00:11:03,140 One of the really big ones that's used for is lateral movement and privilege escalation. 108 00:11:03,420 --> 00:11:07,740 Lateral movement specifically for the PS exec, you have PS remoting, you have WIME. 109 00:11:07,740 --> 00:11:10,720 All those things are all leveraged using PowerShell. 110 00:11:10,720 --> 00:11:14,620 And then privilege escalation specifically for INVE. 111 00:11:14,660 --> 00:11:18,180 So really everybody's still using a lot of offensive PowerShell. 112 00:11:18,180 --> 00:11:20,580 These are some numbers that we pulled pretty recently. 113 00:11:20,580 --> 00:11:25,560 Most of these are within the last couple of months when these reports were published. 114 00:11:25,560 --> 00:11:30,080 Carbon Black put out that about 90% of target attacks are using PowerShell. 115 00:11:30,080 --> 00:11:32,580 So it's a very big significant number. 116 00:11:32,580 --> 00:11:40,000 As well as McAfee for this last quarter put out there was a 689% increase in target attacks using PowerShell. 117 00:11:40,000 --> 00:11:47,880 So not only is PowerShell still being used a lot, its use is increasing significantly by each quarter and every year. 118 00:11:47,880 --> 00:11:54,360 And the last one, CrowdStrike's most recent report said about 50% to 70% of target attacks, they observed PowerShell. 119 00:11:54,360 --> 00:11:59,700 Pretty wide range when you're talking about how many attacks are actually using PowerShell out there. 120 00:12:00,300 --> 00:12:04,620 One of the examples that we're going to talk through is APT33. 121 00:12:04,840 --> 00:12:11,040 If you do some research out there, you can see that they rely pretty significantly on PowerShell to be able to do their stuff. 122 00:12:11,040 --> 00:12:13,820 They are a suspected Iranian threat group. 123 00:12:14,000 --> 00:12:16,520 So they are state sponsored. 124 00:12:16,580 --> 00:12:20,680 And they're really going to be focusing on aerospace and energy industries. 125 00:12:20,680 --> 00:12:23,880 So a lot of defense contractors is what they're really aiming for. 126 00:12:23,880 --> 00:12:30,420 So trying to hurt the industrial base of a country when it comes to defense is really what their target is. 127 00:12:30,420 --> 00:12:38,060 And they're typically employing things like Empire, PowerSploit, and Mimikatz, focusing mostly on the PowerShell side of things. 128 00:12:38,240 --> 00:12:47,020 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. 129 00:12:51,510 --> 00:12:58,530 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. 130 00:12:58,530 --> 00:13:04,750 And what they did was they used a malicious HTA file, which is an HTML executable. 131 00:13:04,750 --> 00:13:10,390 And what that does, it has just a regular HTML on the top part that may point to a certain person. 132 00:13:10,390 --> 00:13:14,130 In this case, it was this aircraft company. 133 00:13:14,130 --> 00:13:17,370 And then after all that HTML, they embed a script. 134 00:13:17,370 --> 00:13:25,650 So the script that they're running launches a PowerShell hidden window with a base64 encoded payload attached to that. 135 00:13:25,650 --> 00:13:30,430 And this launching method is actually very similar to how Empire does a lot of their things. 136 00:13:30,430 --> 00:13:33,110 So you're talking about emulating what the threat does. 137 00:13:33,110 --> 00:13:38,970 Empire emulates this threat pretty well, especially with the HTA file. 138 00:13:43,630 --> 00:13:46,450 Next is WastedLocker ransomware. 139 00:13:46,450 --> 00:13:49,110 This has been pretty popular in the news recently. 140 00:13:49,110 --> 00:13:52,190 This is from the EvilCorp group or Drydex. 141 00:13:52,190 --> 00:13:56,610 And what this does is it leverages a few different things to be able to launch the ransomware. 142 00:13:56,610 --> 00:14:01,890 First, it leverages a CobaltStrikeBeacon and PowerView, kind of get that initial foothold. 143 00:14:01,890 --> 00:14:05,850 And it contains both PowerShell, JavaScript, and .NET. 144 00:14:05,850 --> 00:14:10,930 So it's really leveraging everything when you look at how they go about launching this ransomware. 145 00:14:10,930 --> 00:14:22,230 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. 146 00:14:22,230 --> 00:14:25,950 And once that ransomware is in place, that's really where they're going to make their money. 147 00:14:25,950 --> 00:14:31,150 They're going to lock down companies, individuals, whatever they can, their machines. 148 00:14:31,190 --> 00:14:36,710 They're going to put out a Bitcoin address or whatever other cryptocurrency they want to get paid in. 149 00:14:36,930 --> 00:14:43,050 And they're going to then hide those keys until you guys pay the fees. 150 00:14:43,050 --> 00:14:45,470 And they've been very, very successful with this. 151 00:14:45,470 --> 00:14:51,230 The numbers being reported at the moment is they've made at least $100 million using this sort of ransomware. 152 00:14:51,230 --> 00:14:54,190 So it's a very profitable business for a threat to be able to use. 153 00:14:54,190 --> 00:15:01,110 So being able to see how they do it and then emulate what parts we can is very, very important. 154 00:15:02,710 --> 00:15:14,110 Yeah, and then this comes from a case study that Microsoft did on a breach that happened to Nepone Telegraph and Telephone. 155 00:15:14,450 --> 00:15:28,170 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. 156 00:15:28,170 --> 00:15:47,130 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. 157 00:15:47,130 --> 00:16:08,850 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. 158 00:16:09,350 --> 00:16:15,150 They still ended up utilizing PowerShell through several of the steps to pivot through. 159 00:16:17,560 --> 00:16:21,160 So they used phishing to get an initial foothold. 160 00:16:21,160 --> 00:16:25,800 Once they had that initial foothold, they were able to gain domain information. 161 00:16:25,800 --> 00:16:38,220 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. 162 00:16:38,220 --> 00:16:47,820 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. 163 00:16:50,100 --> 00:16:59,200 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. 164 00:16:59,580 --> 00:17:07,620 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. 165 00:17:08,000 --> 00:17:17,600 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. 166 00:17:17,600 --> 00:17:29,600 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. 167 00:17:29,600 --> 00:17:35,040 Then they were able to brute force those accounts to start trying to get access to server A. 168 00:17:36,180 --> 00:17:46,340 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. 169 00:17:46,340 --> 00:17:53,220 Once the Active Directory server was compromised, they added a backdoor into it to maintain persistence. 170 00:17:53,660 --> 00:17:58,380 And if you look at these images, those are just showing some of the PowerShell they used. 171 00:17:58,380 --> 00:18:11,020 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. 172 00:18:11,460 --> 00:18:21,560 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. 173 00:18:21,560 --> 00:18:32,100 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. 174 00:18:32,100 --> 00:18:36,180 And what was going on here was they were getting an initial foothold inside the network. 175 00:18:36,400 --> 00:18:38,640 They were trying to stay as lean as possible. 176 00:18:38,640 --> 00:18:44,260 They were going out through the web, reaching out to our GitHub, which we hosted Empire. 177 00:18:44,260 --> 00:18:48,400 They went specifically to one module, which was our Invoke Mimikatz module. 178 00:18:48,400 --> 00:18:53,440 Since we keep that pretty up to date, they were downloading that right onto the network so they can run it locally. 179 00:18:53,440 --> 00:18:56,520 And that way they could run Invoke Mimikatz completely locally. 180 00:18:56,520 --> 00:19:03,460 This technique of downloading things from GitHub and other destinations is a pretty popular technique among APTs. 181 00:19:03,460 --> 00:19:06,180 And you can find it in the CrowdStrike report for 2020. 182 00:19:06,240 --> 00:19:07,760 It's pretty widely used. 183 00:19:07,760 --> 00:19:14,820 One of the interesting traits about this though that really stood out to us was the fact that they were running things completely unobfuscated. 184 00:19:14,820 --> 00:19:20,880 They were running it just without any obfuscation or if they had any evasion at all, it was very, very basic techniques. 185 00:19:20,880 --> 00:19:27,420 Normally, you wouldn't see this from a threat, but it actually had some really interesting results from it. 186 00:19:27,420 --> 00:19:34,460 First, the defenders on this network waived it off initially because they thought it was the internal red team practicing. 187 00:19:34,460 --> 00:19:44,660 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. 188 00:19:44,660 --> 00:19:48,440 So being unobfuscated in this case actually worked to their advantage. 189 00:19:48,440 --> 00:19:52,920 They still ended up getting caught eventually, but it really was a benefit for them. 190 00:19:53,780 --> 00:19:54,040 Yeah. 191 00:19:54,040 --> 00:20:04,220 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. 192 00:20:04,220 --> 00:20:09,100 It was just initially, they thought they waived it off the activity. 193 00:20:09,100 --> 00:20:18,900 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. 194 00:20:19,740 --> 00:20:35,140 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. 195 00:20:35,140 --> 00:20:47,360 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. 196 00:20:47,360 --> 00:20:57,160 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. 197 00:20:57,160 --> 00:21:06,340 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. 198 00:21:06,340 --> 00:21:12,840 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. 199 00:21:13,200 --> 00:21:21,760 So it's not the protections that we often see it portrayed as in the offset community. 200 00:21:22,940 --> 00:21:31,180 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. 201 00:21:31,180 --> 00:21:38,780 And then also just something else to note is that, you know, AMSI has already been incorporated into .NET. 202 00:21:38,780 --> 00:21:51,780 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. 203 00:21:51,780 --> 00:22:10,940 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. 204 00:22:13,060 --> 00:22:17,200 So now we're going to talk about AMSI in a little more in-depth. 205 00:22:17,200 --> 00:22:23,660 We hear about it a lot, but often people don't really fully understand exactly how AMSI is working. 206 00:22:23,660 --> 00:22:28,120 So AMSI is the Windows Anti-Malware Scan Interface. 207 00:22:28,120 --> 00:22:33,600 I'm going to go ahead and read off the Microsoft definition for you guys. 208 00:22:33,940 --> 00:22:42,420 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. 209 00:22:42,420 --> 00:22:47,700 AMSI provides enhanced malware protection for your end users and their data applications and workloads. 210 00:22:50,220 --> 00:22:53,680 So that's great, but kind of what does it mean? 211 00:22:53,800 --> 00:22:57,880 And what that means is that AMSI, first of all, doesn't work with just PowerShell. 212 00:22:57,880 --> 00:23:03,520 It works with VBScript, it works with JScript, as well as other applications that we want to send information to. 213 00:23:03,520 --> 00:23:16,000 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. 214 00:23:16,140 --> 00:23:28,160 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. 215 00:23:28,220 --> 00:23:38,400 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. 216 00:23:38,880 --> 00:23:43,460 So a lot of obfuscation that is put in place is removed before AMSI even looks at it. 217 00:23:43,460 --> 00:23:48,140 And this is just a diagram of how that data flows through those layers. 218 00:23:50,980 --> 00:23:54,540 So as I said, it evaluates commands at runtime. 219 00:23:54,580 --> 00:24:16,200 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. 220 00:24:16,320 --> 00:24:19,430 So it helps us identify fileless threats. 221 00:24:20,100 --> 00:24:36,180 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. 222 00:24:36,180 --> 00:24:38,720 So they actually all end up running in the same area. 223 00:24:38,720 --> 00:24:43,300 And now C Sharp also uses the common language runtime. 224 00:24:43,460 --> 00:24:50,780 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. 225 00:24:51,560 --> 00:24:54,580 So AMSI is actually pretty powerful. 226 00:24:54,580 --> 00:24:58,540 And we'll talk... we've got a couple examples that we're going to go through here. 227 00:24:59,020 --> 00:25:02,880 One that Anthony will talk to more when we get to the obfuscation stuff. 228 00:25:02,880 --> 00:25:09,500 But this is just what a standard Empire implant looks like when you put everything in. 229 00:25:09,840 --> 00:25:14,500 And if we just make some changes on the structure of the code, it still goes through AMSI. 230 00:25:14,500 --> 00:25:18,380 Like it's still very, very heavily dependent on static signatures. 231 00:25:19,880 --> 00:25:22,660 So this is just our modified script. 232 00:25:22,660 --> 00:25:33,240 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. 233 00:25:33,240 --> 00:25:35,040 It just had to be ran before the end of the script. 234 00:25:35,040 --> 00:25:36,460 So we moved it around. 235 00:25:36,460 --> 00:25:38,080 And now it runs without issue. 236 00:25:38,080 --> 00:25:40,380 Well, this did run without issue. 237 00:25:40,380 --> 00:25:44,080 They are constantly updating signatures in this one. 238 00:25:44,080 --> 00:25:48,560 This specific implementation probably will not pass AMSI anymore. 239 00:25:48,660 --> 00:25:59,820 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. 240 00:25:59,820 --> 00:26:09,420 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? 241 00:26:10,400 --> 00:26:15,400 So that way it's always avoiding AMSI and Microsoft and all the defenses that are out there. 242 00:26:15,400 --> 00:26:18,000 And it's really just a cat and mouse game at the end of the day. 243 00:26:18,000 --> 00:26:23,860 So if we go and update it, it's going to take them, you know, hours to get the new signatures updated. 244 00:26:23,860 --> 00:26:26,400 And then whatever all the work that we just did is now worthless. 245 00:26:26,460 --> 00:26:32,180 So for us, it's easy for us to easily make these changes and do it, but not publish it out there. 246 00:26:32,180 --> 00:26:34,680 So that's just something that we see a lot. 247 00:26:34,680 --> 00:26:40,340 And we get a lot of questions asked of just why we're not making these changes on the releasable stuff for Empire. 248 00:26:40,420 --> 00:26:54,640 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. 249 00:26:54,640 --> 00:26:57,020 So there's plenty of information out there. 250 00:26:57,660 --> 00:27:00,160 So now we're going to talk about script block logging. 251 00:27:00,160 --> 00:27:05,400 It was first introduced in PowerShell version 4, but it was fairly rudimentary at that time. 252 00:27:05,500 --> 00:27:09,100 Version 5 introduced what Microsoft calls deep script block logging. 253 00:27:09,140 --> 00:27:17,560 What that means is that it follows the execution down through multiple levels, which we'll talk through in a second on these images. 254 00:27:18,000 --> 00:27:24,100 And then it's event ID 4104, if you go look at the PowerShell operational log in Event Viewer. 255 00:27:24,600 --> 00:27:33,200 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. 256 00:27:33,340 --> 00:27:52,540 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. 257 00:27:52,540 --> 00:28:11,120 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. 258 00:28:11,120 --> 00:28:16,660 And we won't see it on the transcription log, we just see what is entered into the command line. 259 00:28:16,660 --> 00:28:24,880 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. 260 00:28:25,140 --> 00:28:31,000 The next one down is you're running that decrypted equals super decrypt to run our function. 261 00:28:31,000 --> 00:28:36,440 Walk down to the next line, where you see invoke expression of the decrypted variable. 262 00:28:36,720 --> 00:28:44,480 And then this is where that kind of deep script block logging and following the things down becomes powerful for AMSI. 263 00:28:44,720 --> 00:28:52,220 After all of that, we see that what was actually executed from that encrypted string is that write host pwned. 264 00:28:52,760 --> 00:29:09,420 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. 265 00:29:09,560 --> 00:29:13,160 And that's what makes AMSI power or script block logging powerful. 266 00:29:13,160 --> 00:29:20,660 But we'll talk about some ways that you can actually obfuscate the script block logging in a little bit later. 267 00:29:23,560 --> 00:29:33,940 So module logging, it was introduced in PowerShell version 3, and I think is the most powerful part of the PowerShell logging capabilities. 268 00:29:33,940 --> 00:29:40,020 It does have some issues in implementing and building proper signatures, because it does report each module individually. 269 00:29:40,140 --> 00:29:46,200 But it's nearly impossible to hit the log without being unobfuscated. 270 00:29:46,200 --> 00:29:58,820 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. 271 00:29:58,820 --> 00:30:11,240 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. 272 00:30:11,240 --> 00:30:14,960 That's telling us what module is being ran, which commandlet. 273 00:30:15,280 --> 00:30:19,380 And then the next line down, you know, says parameter binding. 274 00:30:19,380 --> 00:30:22,060 And then if you go all the way over to the right, it says value. 275 00:30:22,460 --> 00:30:25,320 And that is what is being passed to the commandlet. 276 00:30:25,700 --> 00:30:29,880 And that value is always unobfuscated from what I've seen. 277 00:30:29,880 --> 00:30:35,920 If someone knows of a way obfuscating this, I'd be really interested in hearing about it afterwards. 278 00:30:36,360 --> 00:30:44,160 But that's why it's so powerful, is the values being passed in as arguments for commandlets are always unobfuscated. 279 00:30:44,160 --> 00:30:46,700 But it produces a whole lot of alerts. 280 00:30:47,340 --> 00:31:05,720 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. 281 00:31:05,780 --> 00:31:17,960 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. 282 00:31:21,020 --> 00:31:30,200 So PowerShell logging would make for a bad day for red teams if organizations actually use it properly. 283 00:31:30,200 --> 00:31:37,060 But unfortunately, we have a bunch of things that are in the operational world that are, you know, making that more difficult. 284 00:31:37,060 --> 00:31:40,440 You see alert fatigue, you know, administrators are using sketchy scripts. 285 00:31:40,440 --> 00:31:51,240 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. 286 00:31:51,460 --> 00:32:12,120 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. 287 00:32:12,640 --> 00:32:26,200 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. 288 00:32:26,320 --> 00:32:39,940 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. 289 00:32:39,940 --> 00:32:52,620 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. 290 00:32:52,620 --> 00:32:57,820 And then deep script block logging can result in multiple alerts for a single script execution. 291 00:32:58,000 --> 00:33:07,640 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. 292 00:33:07,980 --> 00:33:18,460 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. 293 00:33:18,460 --> 00:33:25,960 And when you enable that, your logs jump to 96,000 events totaling 50 megabytes of logs for running one script. 294 00:33:26,460 --> 00:33:46,180 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. 295 00:33:46,180 --> 00:33:59,220 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. 296 00:34:03,070 --> 00:34:07,470 So this is just a quick overview of kind of what Mandiant says. 297 00:34:07,470 --> 00:34:10,290 Should they recommend for doing logging? 298 00:34:10,290 --> 00:34:16,710 They say if you can to enable module logging, script block logging, and transcription. 299 00:34:17,010 --> 00:34:20,570 We didn't really talk about transcription because it's fairly straightforward. 300 00:34:20,570 --> 00:34:24,870 All it is, is recording what is written out on the command line. 301 00:34:25,210 --> 00:34:27,350 And it doesn't include... that's all it includes. 302 00:34:27,350 --> 00:34:35,430 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. 303 00:34:36,190 --> 00:34:39,710 And they say the unique data is recorded by each source. 304 00:34:39,750 --> 00:34:48,350 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. 305 00:34:48,590 --> 00:34:57,530 They say where log sizes cannot be significantly increased, only enable script block logging and transcription logging because it will cover most data. 306 00:34:58,430 --> 00:35:01,170 And module logging only buys you some. 307 00:35:01,170 --> 00:35:14,770 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. 308 00:35:15,050 --> 00:35:20,270 And then module logging is basically impossible to hit unobfuscated. 309 00:35:20,270 --> 00:35:25,130 So it provides much better insight, in my opinion, but does produce a whole bunch of data. 310 00:35:25,130 --> 00:35:28,730 And because events are individual, correlating them becomes harder. 311 00:35:29,010 --> 00:35:38,450 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. 312 00:35:38,810 --> 00:35:44,650 We'll go over a little bit of AMSI bypasses, some obfuscation, like standard obfuscation. 313 00:35:44,650 --> 00:35:57,790 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. 314 00:35:57,790 --> 00:36:03,290 We'll talk a little bit about script block logging bypasses and then event tracing bypasses. 315 00:36:03,290 --> 00:36:05,910 Those will be primarily in the demo. 316 00:36:07,250 --> 00:36:09,390 So reflective bypass. 317 00:36:09,390 --> 00:36:12,390 It's the simplest bypass that currently works. 318 00:36:12,390 --> 00:36:18,130 It grabs the systemmanagement.automation.amsi.utils.dll. 319 00:36:18,130 --> 00:36:24,850 It grabs a reference to it and then changes a field that says AMSI init failed and sets it to true. 320 00:36:24,850 --> 00:36:49,990 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. 321 00:36:50,530 --> 00:36:56,290 So when we're reflectively setting this field, we're saying that the initialization of AMSI failed. 322 00:36:56,290 --> 00:37:01,930 So just go ahead and return a clean finding regardless of what was actually done. 323 00:37:02,190 --> 00:37:04,070 And it doesn't even bother scanning the code. 324 00:37:04,070 --> 00:37:06,170 It just says there's something broken with AMSI. 325 00:37:06,170 --> 00:37:14,810 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. 326 00:37:14,810 --> 00:37:23,150 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. 327 00:37:23,170 --> 00:37:30,570 So a more complicated bypass we can look at, and there's a bunch of different implementations floating around. 328 00:37:30,570 --> 00:37:37,210 This is one I wrote based off of Tal Lieberman's work that he published at BlackHat. 329 00:37:37,510 --> 00:37:51,070 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. 330 00:37:51,490 --> 00:38:00,870 So this is using some a C-sharp to export DOL functions to allow us to access some areas of memory. 331 00:38:01,410 --> 00:38:13,370 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. 332 00:38:13,370 --> 00:38:16,510 And if it's over x amount, that's considered bad. 333 00:38:16,510 --> 00:38:21,390 If it's under x amount, then it's considered mostly good. 334 00:38:21,390 --> 00:38:23,510 And if it's a zero, it's considered good. 335 00:38:23,510 --> 00:38:26,150 Basically, you never see zero returned in real life. 336 00:38:26,150 --> 00:38:35,890 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. 337 00:38:35,990 --> 00:38:39,870 There's actually a couple others for policy implementation issues. 338 00:38:39,870 --> 00:38:44,750 But those are the three returns if it's just scanning your code without outside influence. 339 00:38:44,750 --> 00:38:53,810 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. 340 00:38:53,810 --> 00:39:02,610 It says just return a good value from the comparison and say that the script is fine. 341 00:39:02,610 --> 00:39:13,470 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. 342 00:39:13,470 --> 00:39:15,270 We can modify it however we please. 343 00:39:15,270 --> 00:39:22,050 And so the reflective DLL tells AMSI to return a clean result prior to scanning it. 344 00:39:22,050 --> 00:39:26,570 And as I mentioned, the patched one tells it to return after it being scanned. 345 00:39:28,350 --> 00:39:39,210 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. 346 00:39:39,310 --> 00:39:42,970 It's still very, very effective, but it does come with some costs. 347 00:39:42,970 --> 00:39:45,250 One of those being the complexity of your payload. 348 00:39:45,250 --> 00:39:51,090 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. 349 00:39:51,090 --> 00:39:56,730 You may be encoding it on top of changing variable names and splitting things up. 350 00:39:56,790 --> 00:40:03,030 So you can easily exceed limits that are put in place by PowerShell on the size of a command. 351 00:40:03,030 --> 00:40:05,250 It also takes a lot of time to be able to encode these. 352 00:40:05,250 --> 00:40:12,570 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. 353 00:40:12,570 --> 00:40:17,670 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. 354 00:40:17,670 --> 00:40:32,870 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. 355 00:40:32,870 --> 00:40:38,730 So that way they might not be identified, but if they're waiting to the end to run their analysis, you may get caught. 356 00:40:39,730 --> 00:40:47,090 Here's just an example of some unobfuscated and obfuscated code for a launcher for Empire. 357 00:40:47,410 --> 00:40:52,190 The left one just shows the basic payload without any obfuscation in it. 358 00:40:52,190 --> 00:40:57,190 The right one has just the standard token all obfuscation set in place. 359 00:40:57,270 --> 00:41:00,190 And what it does, you can see here, it starts breaking things up. 360 00:41:00,190 --> 00:41:01,810 It starts encoding things. 361 00:41:01,810 --> 00:41:07,750 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. 362 00:41:07,830 --> 00:41:10,750 I'm sure Hubble will want to chime in a little bit on that. 363 00:41:10,750 --> 00:41:20,210 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. 364 00:41:20,690 --> 00:41:34,450 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. 365 00:41:34,450 --> 00:41:36,910 And it has kind of two issues. 366 00:41:36,910 --> 00:41:38,050 One, it's pseudo-random. 367 00:41:38,050 --> 00:41:41,930 At this point, invoke obfuscation has been out for a very long time. 368 00:41:42,250 --> 00:41:50,750 And all of the randomization, or all of the combinations for those six techniques that it has, are fairly well known at this point. 369 00:41:50,750 --> 00:41:56,450 And then there's also some issues with certain techniques interfere with each other if they're ran in the wrong order. 370 00:41:56,590 --> 00:42:10,390 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. 371 00:42:10,750 --> 00:42:18,730 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. 372 00:42:18,930 --> 00:42:22,590 So some of these things work better if you run them in specific orders. 373 00:42:22,590 --> 00:42:26,490 And invoke obfuscation's token all doesn't always do that. 374 00:42:26,490 --> 00:42:28,410 So that's just some of the limitations on it. 375 00:42:28,410 --> 00:42:34,050 And just having those custom cocktails of different obfuscation techniques make a big difference. 376 00:42:34,050 --> 00:42:39,030 I know we have a couple that we keep for ourselves that seem to work almost all the time. 377 00:42:40,650 --> 00:42:44,590 So the obfuscation really does get you about 90% of the way there. 378 00:42:44,590 --> 00:42:48,970 Like I said, those custom cocktails that we have really do get us most of the way there. 379 00:42:48,970 --> 00:42:52,370 But there's some things that you just can't get rid of when you're obfuscating. 380 00:42:52,370 --> 00:42:58,670 And those are just like those common signatures that require you to restructure the code or eliminate certain keywords. 381 00:42:58,670 --> 00:43:04,450 One of the really good examples was something that we saw last year with the original Empire project. 382 00:43:04,450 --> 00:43:11,550 Prior to version 3, there was actually a mistake inside of the code where it double appended one of the headers. 383 00:43:11,710 --> 00:43:16,550 This allowed signatures to be based off of that issue, because it couldn't be obfuscated away. 384 00:43:16,750 --> 00:43:22,070 So any virus and AMSI and everything was detecting off of this specific mistake in the code. 385 00:43:22,070 --> 00:43:30,190 So just removing that and then rerunning the obfuscation with a slightly different technique allowed the payload to get through completely undetected. 386 00:43:30,190 --> 00:43:36,510 So really, that restructuring and making sure that those signatures are broken is really, really important. 387 00:43:36,590 --> 00:43:42,570 So now we're going to talk a little bit more about what we kind of call keyword aliasing. 388 00:43:42,730 --> 00:43:53,730 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. 389 00:43:53,730 --> 00:43:57,390 And these can be triggered even when not ran directly by AMSI. 390 00:43:57,390 --> 00:44:08,550 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. 391 00:44:08,550 --> 00:44:13,890 So then it starts searching strings in memory, or Defender starts searching for strings in memory. 392 00:44:13,890 --> 00:44:23,190 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. 393 00:44:23,190 --> 00:44:38,090 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. 394 00:44:38,090 --> 00:44:46,450 Some of these strings to keep in mind are actually invokeMimikatz, invokeEmpire, powersploit. 395 00:44:47,010 --> 00:45:03,230 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. 396 00:45:03,430 --> 00:45:13,390 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. 397 00:45:13,430 --> 00:45:22,630 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. 398 00:45:22,710 --> 00:45:32,230 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. 399 00:45:32,230 --> 00:45:34,790 It just becomes that is the value that we are using. 400 00:45:34,790 --> 00:45:45,850 So in the example over on the right, we're changing InvokeMemeCats to QAD45 and InvokeEmpire to DLXZ9. 401 00:45:45,970 --> 00:45:48,250 This is how it's done in Empire now. 402 00:45:48,250 --> 00:45:52,650 On startup, it automatically makes entries to obfuscate those strings. 403 00:45:52,650 --> 00:46:08,070 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? 404 00:46:08,090 --> 00:46:17,390 You could make these something like InvokeFileSearcher, InvokeOrganizer, so that it would look even less suspicious than just a random string. 405 00:46:17,390 --> 00:46:20,690 We don't do this to everything for a couple of reasons. 406 00:46:21,510 --> 00:46:25,650 You could do it, but it's time consuming to pick which values to alias. 407 00:46:25,650 --> 00:46:36,090 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. 408 00:46:36,210 --> 00:46:51,010 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, 409 00:46:51,010 --> 00:46:52,030 then your stuff's going to break. 410 00:46:52,030 --> 00:46:54,630 So there's just some complexity added in the aliasing. 411 00:46:54,630 --> 00:47:02,250 And then, as we mentioned, heavy obfuscation can be a flag in and of itself, so we want to minimally obfuscate where we can. 412 00:47:02,810 --> 00:47:12,510 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. 413 00:47:12,530 --> 00:47:18,750 You can actually import to avoid script logs, as well as the transcription log as well. 414 00:47:18,750 --> 00:47:21,510 ImportAlias is the one I've been playing with the most. 415 00:47:21,510 --> 00:47:28,170 What happens is, when we import our aliases, for those that don't know, let me take a step back. 416 00:47:28,170 --> 00:47:36,090 Aliasing, in terms of PowerShell, allows us to set whatever function name we want for any commandlet. 417 00:47:36,090 --> 00:47:48,890 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. 418 00:47:49,170 --> 00:47:57,490 And then, whenever you type in print into PowerShell, it knows that that is the same as doing get printer. 419 00:47:58,890 --> 00:48:02,970 You can then save those aliases using ExportAlias. 420 00:48:03,390 --> 00:48:13,570 And then, when you import alias, those terms and different names for your commandlets never get seen by the log. 421 00:48:13,570 --> 00:48:15,690 They just get imported into memory. 422 00:48:15,690 --> 00:48:22,110 You can now run the command with the name that you gave it, and on the script block log, that's all it sees. 423 00:48:22,110 --> 00:48:24,090 It'll see print instead of get printer. 424 00:48:24,310 --> 00:48:30,990 If you have module logging enabled, then it will still see the module you're using. 425 00:48:31,290 --> 00:48:41,170 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. 426 00:48:41,170 --> 00:48:45,670 But as we said, it's basically impossible to avoid hitting the module logging initially. 427 00:48:47,570 --> 00:48:51,430 So, this is kind of what it looks like to change things up. 428 00:48:51,430 --> 00:48:57,270 On the right is if I want to do InvokeExpressionNewObjectSystem.net.webClient. 429 00:48:57,450 --> 00:48:58,830 That's what it would look like. 430 00:48:58,830 --> 00:49:01,410 That's what it would look like in the logs. 431 00:49:01,410 --> 00:49:05,670 Instead, to run that, I went and did some aliasing by hand. 432 00:49:07,170 --> 00:49:11,810 And we can embed further commands into the alias description. 433 00:49:11,810 --> 00:49:21,130 And if you look at the import.alias.csv, that imported all of my alias commands. 434 00:49:21,130 --> 00:49:30,350 Now I run this completely nonsensical command to someone looking at it that says I parentheses ca.description. 435 00:49:30,970 --> 00:49:37,510 And then that caused another execution that was bcb.description. 436 00:49:37,930 --> 00:49:44,350 So, in this case, I was was InvokeExpression. 437 00:49:44,350 --> 00:49:47,290 And b was that new object. 438 00:49:47,290 --> 00:49:52,030 And then the description for new object was system.net.webClient. 439 00:49:52,030 --> 00:50:03,250 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. 440 00:50:03,250 --> 00:50:07,990 Because as soon as you close the PowerShell session, the aliasing is gone. 441 00:50:07,990 --> 00:50:11,950 It is not saved saved permanently anywhere. 442 00:50:11,950 --> 00:50:12,930 So, you have to import. 443 00:50:12,930 --> 00:50:18,470 If you want to use aliases consistently, you have to import them each time you start a new PowerShell session. 444 00:50:18,470 --> 00:50:20,710 That's why the function was built. 445 00:50:20,710 --> 00:50:25,350 So, as soon as we kill our PowerShell session, our aliasing is gone. 446 00:50:25,350 --> 00:50:29,170 And the key to what the script block log means is gone as well. 447 00:50:29,530 --> 00:50:48,550 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. 448 00:50:51,250 --> 00:50:58,230 First things first, how you get to the operational log for PowerShell is you're going to use event viewer. 449 00:50:58,370 --> 00:51:01,410 You're going to come down here and type in event viewer. 450 00:51:01,410 --> 00:51:03,430 You want to make sure you run it as an administrator. 451 00:51:03,430 --> 00:51:08,230 That just makes it easier to clear the logs when you're testing that kind of stuff. 452 00:51:08,230 --> 00:51:11,050 But you can't usually view it even as an unprivileged user. 453 00:51:11,050 --> 00:51:12,650 You just can't modify it. 454 00:51:12,670 --> 00:51:26,470 You'll then click on Microsoft, then Windows, then come down here to PowerShell, open PowerShell, and then click on operational. 455 00:51:26,470 --> 00:51:31,510 Right now I cleared the logs prior to starting this so that we can make it easier to see everything. 456 00:51:32,010 --> 00:51:40,290 So, if I go ahead and click on PowerShell and open it, it's actually just starting PowerShell generates some logs. 457 00:51:43,050 --> 00:51:50,290 As you can see here, we get these event IDs showing startup, as well as it looks like my computer was a little slow. 458 00:51:50,290 --> 00:51:52,150 So, if I refresh it again, we should get a few more. 459 00:51:52,150 --> 00:51:53,250 Yeah, there we go. 460 00:51:53,690 --> 00:52:02,390 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. 461 00:52:02,390 --> 00:52:08,890 Then we'll see this strict mode that gets used throughout when you're running PowerShell. 462 00:52:08,910 --> 00:52:17,290 But as you can see, this one's 4104, which is our script block logging, and then we have 4103 is our module logging. 463 00:52:18,190 --> 00:52:32,230 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. 464 00:52:32,230 --> 00:52:35,750 As I said, prompt comes up after every execution. 465 00:52:36,010 --> 00:52:41,510 But if we go down here, we can see this right host test for our script block log in 4104. 466 00:52:42,230 --> 00:52:54,970 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. 467 00:52:55,590 --> 00:52:59,350 So, now we're going to go over here, now that we've seen that. 468 00:53:00,130 --> 00:53:04,350 And the first one we're going to talk about real quick is script block logging. 469 00:53:04,350 --> 00:53:07,170 This was published by Matt Graber. 470 00:53:07,170 --> 00:53:14,230 It's got a few modifications from his original one, but this comes from a default Empire implementation. 471 00:53:14,230 --> 00:53:23,130 All it's doing is it's creating a new dictionary that gets added to our cache group policy settings. 472 00:53:23,130 --> 00:53:29,130 We access that reflectively, and we're just telling it that script block logging has been turned off when it goes. 473 00:53:29,130 --> 00:53:37,530 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. 474 00:53:37,690 --> 00:53:44,590 We're able to do this because, just like the AMD bypass, this is all in our process memory. 475 00:53:44,590 --> 00:53:46,670 So, we have complete access to it. 476 00:53:46,670 --> 00:53:50,250 We can manipulate in essentially whatever way we want. 477 00:53:51,290 --> 00:54:02,130 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. 478 00:54:02,130 --> 00:54:07,330 So, all of that code that we just ran is going to hit our script block logging. 479 00:54:08,230 --> 00:54:14,910 And so, we go up here, and we can see that our script block was ran with all of our different values. 480 00:54:15,210 --> 00:54:23,110 Then we get our out default, which is the module when output is sent to the command line, and then some other ones. 481 00:54:23,110 --> 00:54:30,530 And since script block logging is using an assembly, that doesn't actually generate any module logging because it's obviously not a module. 482 00:54:30,730 --> 00:54:41,870 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. 483 00:54:43,090 --> 00:55:01,450 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. 484 00:55:02,770 --> 00:55:07,710 So now, the other nice part about this is that only affects our local process. 485 00:55:07,710 --> 00:55:14,810 So, if I just close out PowerShell and clear our logs, we will reset everything. 486 00:55:15,370 --> 00:55:32,870 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. 487 00:55:32,870 --> 00:55:35,210 It just never really got a lot of traction. 488 00:55:35,890 --> 00:55:38,950 It's, I believe it's linked in our slides. 489 00:55:38,950 --> 00:55:42,730 If not, I have the link for everyone that I can share. 490 00:55:42,990 --> 00:55:54,410 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. 491 00:55:54,710 --> 00:55:58,950 But instead, we're disabling event tracing, which happens at a lower level. 492 00:55:58,950 --> 00:56:04,090 This event tracing actually disables our module logging as well. 493 00:56:04,390 --> 00:56:11,150 So we run this, and we go look at our logs. 494 00:56:13,110 --> 00:56:15,390 And we'll see that we get a warning level event. 495 00:56:15,390 --> 00:56:35,630 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. 496 00:56:35,630 --> 00:56:44,190 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. 497 00:56:44,190 --> 00:56:45,990 And if we go run that 498 00:56:49,330 --> 00:56:56,190 right host test again, we can see that we have had produced no logs. 499 00:56:56,190 --> 00:57:01,690 So we still have viable ways of totally disabling PowerShell logging. 500 00:57:01,790 --> 00:57:06,350 And like I said, there are ways to get this down, so it won't produce a warning level event. 501 00:57:06,770 --> 00:57:12,830 And then the last thing I was going to show you guys real quick is just that import alias thing we talked about. 502 00:57:12,830 --> 00:57:14,530 I was just going to show it to you real time. 503 00:57:14,530 --> 00:57:17,710 So we'll go ahead and clear the log. 504 00:57:20,630 --> 00:57:23,210 Open PowerShell back up again. 505 00:57:27,010 --> 00:57:31,110 We're just going to go ahead and import our alias.csv. 506 00:57:33,210 --> 00:57:37,270 I'm going to go ahead and run this nonsensical looking thing. 507 00:57:37,270 --> 00:57:45,230 As we can see, it gives us an output that a new web request object was created. 508 00:57:45,250 --> 00:57:47,130 So now when we go look at our logging, 509 00:57:52,030 --> 00:57:56,110 we can see a couple of different script block logs were called. 510 00:57:56,110 --> 00:58:01,310 So I called this ICA.description initially. 511 00:58:01,790 --> 00:58:05,750 And this is where we can see that it's still hitting our module logging. 512 00:58:05,750 --> 00:58:08,390 Even the script block logging can't see it. 513 00:58:08,570 --> 00:58:18,870 It appears that C is aliased to get command, as we can see here. 514 00:58:18,870 --> 00:58:19,990 I'm looking through that. 515 00:58:19,990 --> 00:58:29,590 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. 516 00:58:29,830 --> 00:58:33,390 So we have this value A that gets passed to it. 517 00:58:33,390 --> 00:58:40,570 Then we see it execute this bcb.description, which again is a git command. 518 00:58:40,730 --> 00:58:48,910 And then we also see that we're executing a new object that was being passed a system.net web client. 519 00:58:49,450 --> 00:58:55,590 And so that just shows you module logging is kind of effective at bypassing this import aliasing thing. 520 00:58:55,590 --> 00:59:01,730 But the import aliasing totally obfuscates logs in a way that you can't really undo it. 521 00:59:01,770 --> 00:59:10,190 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. 522 00:59:10,190 --> 00:59:15,550 So when we close out PowerShell, all of our aliasing key is gone, so they can't go look it up. 523 00:59:15,730 --> 00:59:19,410 So it's just another level of obfuscation. 524 00:59:19,410 --> 00:59:22,510 And it also makes it really hard for Amzie to see what's going on. 525 00:59:22,510 --> 00:59:25,090 So that's just something kind of fun to play with. 526 00:59:25,110 --> 00:59:26,290 But that's all I got. 527 00:59:26,290 --> 00:59:28,850 So I'll toss it back over to Anthony. 528 00:59:28,850 --> 00:59:30,830 And we should have just a little bit of time left. 529 00:59:30,990 --> 00:59:33,730 Thanks for having us at the Red Team Village. 530 00:59:33,730 --> 00:59:36,010 We're going to be in the channel for a little bit to answer any questions.