WEBVTT

00:00.000 --> 00:04.100
Welcome everybody to APT's Love PowerShell and Why You Should Too.

00:04.100 --> 00:04.920
I'm Anthony.

00:04.920 --> 00:06.400
I'm here with Jake.

00:06.440 --> 00:10.820
We're going to be going over some of the interesting things that APTs do for PowerShell.

00:10.940 --> 00:11.880
And here we go.

00:12.560 --> 00:14.500
So once again, I'm Anthony.

00:14.500 --> 00:15.460
I go by coin.

00:15.460 --> 00:16.520
That's my handle.

00:16.680 --> 00:20.460
I got a master's in electrical engineering, same with my bachelor's.

00:20.460 --> 00:21.760
Some interesting things about me.

00:21.760 --> 00:23.340
I'm a lock picking hobbyist.

00:23.340 --> 00:24.300
You followed some of my work.

00:24.300 --> 00:29.480
I did some Bluetooth lock picking hacks over the years, as well as some wireless stuff.

00:29.660 --> 00:33.760
And then a lot of my focus recently has been building up Empire and Starkiller.

00:33.760 --> 00:35.600
And then I got Jake here as well.

00:35.980 --> 00:37.120
Yeah, hey guys.

00:37.120 --> 00:41.640
I've got... my background's a BS in astronautical engineering and I have an MBA.

00:41.880 --> 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.

00:53.300 --> 01:00.840
So after that, I ended up as a... doing some cyber testing for fighter aircraft for the Air Force.

01:00.980 --> 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.

01:06.520 --> 01:12.780
And then I got out of the Air Force and now I'm currently focused on embedded systems security.

01:13.200 --> 01:17.760
And I'm kind of our PowerShell obfuscation expert for BC security.

01:17.760 --> 01:19.520
So I spend a lot of time on that too.

01:20.060 --> 01:24.480
So we get told this all the time and ask this question, you know, aren't PowerShell attacks dead?

01:24.480 --> 01:26.600
You know, offensive PowerShell's dead.

01:26.600 --> 01:28.500
Why don't you just move to C-sharp?

01:28.520 --> 01:33.260
Script logging to, you know, makes PowerShell attack completely impossible.

01:33.380 --> 01:36.240
You know, all these sort of things everybody always brings up.

01:36.240 --> 01:40.400
And we're constantly being told this, you know, why use PowerShell?

01:40.400 --> 01:41.420
Isn't it dead?

01:41.780 --> 01:42.260
Yeah.

01:42.260 --> 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.

01:55.140 --> 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.

02:08.940 --> 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.

02:18.080 --> 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.

02:24.240 --> 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.

02:45.040 --> 02:48.420
So obviously PowerShell is really, really dead.

02:48.420 --> 02:53.080
It can't be used for offensive PowerShell anymore.

02:53.100 --> 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.

02:57.900 --> 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.

03:11.580 --> 03:13.760
It's being used for all sorts of things.

03:15.320 --> 03:21.420
Okay, so just a quick primer in case everyone's not fully aware of PowerShell.

03:21.420 --> 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.

03:36.280 --> 03:44.000
It gives us direct access to the Win32 API, which also gives us low level access to operating system functions.

03:44.000 --> 03:50.840
We can operate entirely out of memory, for the most part, and then installed by default in Windows.

03:50.840 --> 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.

03:59.460 --> 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.

04:06.440 --> 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.

04:13.520 --> 04:19.000
Meanwhile, APTs and criminal groups are using PowerShell every day.

04:19.000 --> 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.

04:28.660 --> 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.

04:39.260 --> 04:42.240
So PowerShell version 1 came out in 2006.

04:42.240 --> 04:48.360
It was released for XP, Service Pack 2, Server 2003, and Vista.

04:48.380 --> 04:51.620
When it was first released, it didn't have a ton of capability.

04:51.620 --> 04:54.600
It was kind of more of a novelty thing.

04:55.320 --> 05:00.520
And PowerShell version 2 is when we really saw it start getting widely adopted.

05:00.780 --> 05:04.420
It was fully integrated into Windows 7 and Server 2008.

05:04.640 --> 05:09.820
It introduced a bunch of new features such as PowerShell remoting and background jobs.

05:09.820 --> 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.

05:33.100 --> 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.

05:41.300 --> 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.

05:51.140 --> 05:54.580
If we can run in version 2, that's where we want to be as offensive people.

05:54.620 --> 05:58.340
And version 5 is where we got the full Gucci set of defenses.

05:58.340 --> 06:03.300
It had a few protections, but it had essentially no protections.

06:03.300 --> 06:11.940
And then Trusted Security, David Kennedy and Josh Kelly gave their PowerShell it's time to own talk in 2010.

06:11.940 --> 06:19.380
And that was when we saw the beginning of the wave of offensive use of PowerShell.

06:19.420 --> 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.

06:28.360 --> 06:31.360
So that's when we started seeing people begin to adopt things.

06:32.800 --> 06:36.540
PowerShell version 3 came out two years later in 2012.

06:36.540 --> 06:40.240
It introduced module logging, which we will talk about that more.

06:40.240 --> 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.

06:48.900 --> 06:52.500
But PowerSploit was first published in 2012.

06:52.500 --> 06:56.000
A lot of people don't realize just how old PowerSploit is at this point.

06:56.000 --> 07:02.600
And then Metasploit also introduced its execute PowerShell capability in 2012.

07:03.040 --> 07:06.820
And 2013, PowerShell version 4 came out.

07:06.820 --> 07:09.960
This was where rudimentary strip block logging was introduced.

07:09.960 --> 07:17.000
It's more akin to what PowerShell version 5 referred to as transcription logging.

07:17.000 --> 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.

07:24.460 --> 07:34.500
And then 2014 is where we start seeing like the just overwhelming wave of offensive tooling and everyone adopting it.

07:34.500 --> 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.

07:47.000 --> 07:51.020
PowerShell version 5 was introduced in 2015 slash 2016.

07:51.020 --> 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.

07:59.320 --> 08:02.160
So it sort of has two release dates.

08:02.380 --> 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.

08:20.340 --> 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.

08:35.020 --> 08:39.680
That's also where PowerShell Empire was released as well as PowerPick.

08:39.680 --> 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.

08:57.120 --> 09:01.060
But these are all the APTs that are currently still using PowerShell.

09:01.060 --> 09:02.760
So pretty much everyone.

09:03.720 --> 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.

09:14.720 --> 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.

09:21.140 --> 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.

09:25.880 --> 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.

09:33.460 --> 09:35.380
So be able to do that research.

09:35.500 --> 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.

09:44.780 --> 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.

09:52.680 --> 09:57.700
You can use things like FireEye if you want to pay for some of that threat intelligence info.

09:57.700 --> 10:02.540
Otherwise, another option is always go on to MITRE's page for the attack framework.

10:02.540 --> 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.

10:18.540 --> 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.

10:27.340 --> 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.

10:37.880 --> 10:40.200
Obviously, command and control is a big one.

10:40.200 --> 10:43.460
There's a lot of different C2 frameworks out there that are being used.

10:43.840 --> 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.

10:53.360 --> 10:55.900
PowerShell can be leveraged for their DLL hijacking.

10:55.900 --> 10:57.660
It can be used for key logging.

10:58.020 --> 11:03.140
One of the really big ones that's used for is lateral movement and privilege escalation.

11:03.420 --> 11:07.740
Lateral movement specifically for the PS exec, you have PS remoting, you have WIME.

11:07.740 --> 11:10.720
All those things are all leveraged using PowerShell.

11:10.720 --> 11:14.620
And then privilege escalation specifically for INVE.

11:14.660 --> 11:18.180
So really everybody's still using a lot of offensive PowerShell.

11:18.180 --> 11:20.580
These are some numbers that we pulled pretty recently.

11:20.580 --> 11:25.560
Most of these are within the last couple of months when these reports were published.

11:25.560 --> 11:30.080
Carbon Black put out that about 90% of target attacks are using PowerShell.

11:30.080 --> 11:32.580
So it's a very big significant number.

11:32.580 --> 11:40.000
As well as McAfee for this last quarter put out there was a 689% increase in target attacks using PowerShell.

11:40.000 --> 11:47.880
So not only is PowerShell still being used a lot, its use is increasing significantly by each quarter and every year.

11:47.880 --> 11:54.360
And the last one, CrowdStrike's most recent report said about 50% to 70% of target attacks, they observed PowerShell.

11:54.360 --> 11:59.700
Pretty wide range when you're talking about how many attacks are actually using PowerShell out there.

12:00.300 --> 12:04.620
One of the examples that we're going to talk through is APT33.

12:04.840 --> 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.

12:11.040 --> 12:13.820
They are a suspected Iranian threat group.

12:14.000 --> 12:16.520
So they are state sponsored.

12:16.580 --> 12:20.680
And they're really going to be focusing on aerospace and energy industries.

12:20.680 --> 12:23.880
So a lot of defense contractors is what they're really aiming for.

12:23.880 --> 12:30.420
So trying to hurt the industrial base of a country when it comes to defense is really what their target is.

12:30.420 --> 12:38.060
And they're typically employing things like Empire, PowerSploit, and Mimikatz, focusing mostly on the PowerShell side of things.

12:38.240 --> 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.

12:51.510 --> 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.

12:58.530 --> 13:04.750
And what they did was they used a malicious HTA file, which is an HTML executable.

13:04.750 --> 13:10.390
And what that does, it has just a regular HTML on the top part that may point to a certain person.

13:10.390 --> 13:14.130
In this case, it was this aircraft company.

13:14.130 --> 13:17.370
And then after all that HTML, they embed a script.

13:17.370 --> 13:25.650
So the script that they're running launches a PowerShell hidden window with a base64 encoded payload attached to that.

13:25.650 --> 13:30.430
And this launching method is actually very similar to how Empire does a lot of their things.

13:30.430 --> 13:33.110
So you're talking about emulating what the threat does.

13:33.110 --> 13:38.970
Empire emulates this threat pretty well, especially with the HTA file.

13:43.630 --> 13:46.450
Next is WastedLocker ransomware.

13:46.450 --> 13:49.110
This has been pretty popular in the news recently.

13:49.110 --> 13:52.190
This is from the EvilCorp group or Drydex.

13:52.190 --> 13:56.610
And what this does is it leverages a few different things to be able to launch the ransomware.

13:56.610 --> 14:01.890
First, it leverages a CobaltStrikeBeacon and PowerView, kind of get that initial foothold.

14:01.890 --> 14:05.850
And it contains both PowerShell, JavaScript, and .NET.

14:05.850 --> 14:10.930
So it's really leveraging everything when you look at how they go about launching this ransomware.

14:10.930 --> 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.

14:22.230 --> 14:25.950
And once that ransomware is in place, that's really where they're going to make their money.

14:25.950 --> 14:31.150
They're going to lock down companies, individuals, whatever they can, their machines.

14:31.190 --> 14:36.710
They're going to put out a Bitcoin address or whatever other cryptocurrency they want to get paid in.

14:36.930 --> 14:43.050
And they're going to then hide those keys until you guys pay the fees.

14:43.050 --> 14:45.470
And they've been very, very successful with this.

14:45.470 --> 14:51.230
The numbers being reported at the moment is they've made at least $100 million using this sort of ransomware.

14:51.230 --> 14:54.190
So it's a very profitable business for a threat to be able to use.

14:54.190 --> 15:01.110
So being able to see how they do it and then emulate what parts we can is very, very important.

15:02.710 --> 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.

15:14.450 --> 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.

15:28.170 --> 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.

15:47.130 --> 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.

16:09.350 --> 16:15.150
They still ended up utilizing PowerShell through several of the steps to pivot through.

16:17.560 --> 16:21.160
So they used phishing to get an initial foothold.

16:21.160 --> 16:25.800
Once they had that initial foothold, they were able to gain domain information.

16:25.800 --> 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.

16:38.220 --> 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.

16:50.100 --> 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.

16:59.580 --> 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.

17:08.000 --> 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.

17:17.600 --> 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.

17:29.600 --> 17:35.040
Then they were able to brute force those accounts to start trying to get access to server A.

17:36.180 --> 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.

17:46.340 --> 17:53.220
Once the Active Directory server was compromised, they added a backdoor into it to maintain persistence.

17:53.660 --> 17:58.380
And if you look at these images, those are just showing some of the PowerShell they used.

17:58.380 --> 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.

18:11.460 --> 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.

18:21.560 --> 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.

18:32.100 --> 18:36.180
And what was going on here was they were getting an initial foothold inside the network.

18:36.400 --> 18:38.640
They were trying to stay as lean as possible.

18:38.640 --> 18:44.260
They were going out through the web, reaching out to our GitHub, which we hosted Empire.

18:44.260 --> 18:48.400
They went specifically to one module, which was our Invoke Mimikatz module.

18:48.400 --> 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.

18:53.440 --> 18:56.520
And that way they could run Invoke Mimikatz completely locally.

18:56.520 --> 19:03.460
This technique of downloading things from GitHub and other destinations is a pretty popular technique among APTs.

19:03.460 --> 19:06.180
And you can find it in the CrowdStrike report for 2020.

19:06.240 --> 19:07.760
It's pretty widely used.

19:07.760 --> 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.

19:14.820 --> 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.

19:20.880 --> 19:27.420
Normally, you wouldn't see this from a threat, but it actually had some really interesting results from it.

19:27.420 --> 19:34.460
First, the defenders on this network waived it off initially because they thought it was the internal red team practicing.

19:34.460 --> 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.

19:44.660 --> 19:48.440
So being unobfuscated in this case actually worked to their advantage.

19:48.440 --> 19:52.920
They still ended up getting caught eventually, but it really was a benefit for them.

19:53.780 --> 19:54.040
Yeah.

19:54.040 --> 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.

20:04.220 --> 20:09.100
It was just initially, they thought they waived it off the activity.

20:09.100 --> 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.

20:19.740 --> 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.

20:35.140 --> 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.

20:47.360 --> 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.

20:57.160 --> 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.

21:06.340 --> 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.

21:13.200 --> 21:21.760
So it's not the protections that we often see it portrayed as in the offset community.

21:22.940 --> 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.

21:31.180 --> 21:38.780
And then also just something else to note is that, you know, AMSI has already been incorporated into .NET.

21:38.780 --> 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.

21:51.780 --> 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.

22:13.060 --> 22:17.200
So now we're going to talk about AMSI in a little more in-depth.

22:17.200 --> 22:23.660
We hear about it a lot, but often people don't really fully understand exactly how AMSI is working.

22:23.660 --> 22:28.120
So AMSI is the Windows Anti-Malware Scan Interface.

22:28.120 --> 22:33.600
I'm going to go ahead and read off the Microsoft definition for you guys.

22:33.940 --> 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.

22:42.420 --> 22:47.700
AMSI provides enhanced malware protection for your end users and their data applications and workloads.

22:50.220 --> 22:53.680
So that's great, but kind of what does it mean?

22:53.800 --> 22:57.880
And what that means is that AMSI, first of all, doesn't work with just PowerShell.

22:57.880 --> 23:03.520
It works with VBScript, it works with JScript, as well as other applications that we want to send information to.

23:03.520 --> 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.

23:16.140 --> 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.

23:28.220 --> 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.

23:38.880 --> 23:43.460
So a lot of obfuscation that is put in place is removed before AMSI even looks at it.

23:43.460 --> 23:48.140
And this is just a diagram of how that data flows through those layers.

23:50.980 --> 23:54.540
So as I said, it evaluates commands at runtime.

23:54.580 --> 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.

24:16.320 --> 24:19.430
So it helps us identify fileless threats.

24:20.100 --> 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.

24:36.180 --> 24:38.720
So they actually all end up running in the same area.

24:38.720 --> 24:43.300
And now C Sharp also uses the common language runtime.

24:43.460 --> 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.

24:51.560 --> 24:54.580
So AMSI is actually pretty powerful.

24:54.580 --> 24:58.540
And we'll talk... we've got a couple examples that we're going to go through here.

24:59.020 --> 25:02.880
One that Anthony will talk to more when we get to the obfuscation stuff.

25:02.880 --> 25:09.500
But this is just what a standard Empire implant looks like when you put everything in.

25:09.840 --> 25:14.500
And if we just make some changes on the structure of the code, it still goes through AMSI.

25:14.500 --> 25:18.380
Like it's still very, very heavily dependent on static signatures.

25:19.880 --> 25:22.660
So this is just our modified script.

25:22.660 --> 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.

25:33.240 --> 25:35.040
It just had to be ran before the end of the script.

25:35.040 --> 25:36.460
So we moved it around.

25:36.460 --> 25:38.080
And now it runs without issue.

25:38.080 --> 25:40.380
Well, this did run without issue.

25:40.380 --> 25:44.080
They are constantly updating signatures in this one.

25:44.080 --> 25:48.560
This specific implementation probably will not pass AMSI anymore.

25:48.660 --> 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.

25:59.820 --> 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?

26:10.400 --> 26:15.400
So that way it's always avoiding AMSI and Microsoft and all the defenses that are out there.

26:15.400 --> 26:18.000
And it's really just a cat and mouse game at the end of the day.

26:18.000 --> 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.

26:23.860 --> 26:26.400
And then whatever all the work that we just did is now worthless.

26:26.460 --> 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.

26:32.180 --> 26:34.680
So that's just something that we see a lot.

26:34.680 --> 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.

26:40.420 --> 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.

26:54.640 --> 26:57.020
So there's plenty of information out there.

26:57.660 --> 27:00.160
So now we're going to talk about script block logging.

27:00.160 --> 27:05.400
It was first introduced in PowerShell version 4, but it was fairly rudimentary at that time.

27:05.500 --> 27:09.100
Version 5 introduced what Microsoft calls deep script block logging.

27:09.140 --> 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.

27:18.000 --> 27:24.100
And then it's event ID 4104, if you go look at the PowerShell operational log in Event Viewer.

27:24.600 --> 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.

27:33.340 --> 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.

27:52.540 --> 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.

28:11.120 --> 28:16.660
And we won't see it on the transcription log, we just see what is entered into the command line.

28:16.660 --> 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.

28:25.140 --> 28:31.000
The next one down is you're running that decrypted equals super decrypt to run our function.

28:31.000 --> 28:36.440
Walk down to the next line, where you see invoke expression of the decrypted variable.

28:36.720 --> 28:44.480
And then this is where that kind of deep script block logging and following the things down becomes powerful for AMSI.

28:44.720 --> 28:52.220
After all of that, we see that what was actually executed from that encrypted string is that write host pwned.

28:52.760 --> 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.

29:09.560 --> 29:13.160
And that's what makes AMSI power or script block logging powerful.

29:13.160 --> 29:20.660
But we'll talk about some ways that you can actually obfuscate the script block logging in a little bit later.

29:23.560 --> 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.

29:33.940 --> 29:40.020
It does have some issues in implementing and building proper signatures, because it does report each module individually.

29:40.140 --> 29:46.200
But it's nearly impossible to hit the log without being unobfuscated.

29:46.200 --> 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.

29:58.820 --> 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.

30:11.240 --> 30:14.960
That's telling us what module is being ran, which commandlet.

30:15.280 --> 30:19.380
And then the next line down, you know, says parameter binding.

30:19.380 --> 30:22.060
And then if you go all the way over to the right, it says value.

30:22.460 --> 30:25.320
And that is what is being passed to the commandlet.

30:25.700 --> 30:29.880
And that value is always unobfuscated from what I've seen.

30:29.880 --> 30:35.920
If someone knows of a way obfuscating this, I'd be really interested in hearing about it afterwards.

30:36.360 --> 30:44.160
But that's why it's so powerful, is the values being passed in as arguments for commandlets are always unobfuscated.

30:44.160 --> 30:46.700
But it produces a whole lot of alerts.

30:47.340 --> 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.

31:05.780 --> 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.

31:21.020 --> 31:30.200
So PowerShell logging would make for a bad day for red teams if organizations actually use it properly.

31:30.200 --> 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.

31:37.060 --> 31:40.440
You see alert fatigue, you know, administrators are using sketchy scripts.

31:40.440 --> 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.

31:51.460 --> 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.

32:12.640 --> 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.

32:26.320 --> 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.

32:39.940 --> 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.

32:52.620 --> 32:57.820
And then deep script block logging can result in multiple alerts for a single script execution.

32:58.000 --> 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.

33:07.980 --> 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.

33:18.460 --> 33:25.960
And when you enable that, your logs jump to 96,000 events totaling 50 megabytes of logs for running one script.

33:26.460 --> 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.

33:46.180 --> 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.

34:03.070 --> 34:07.470
So this is just a quick overview of kind of what Mandiant says.

34:07.470 --> 34:10.290
Should they recommend for doing logging?

34:10.290 --> 34:16.710
They say if you can to enable module logging, script block logging, and transcription.

34:17.010 --> 34:20.570
We didn't really talk about transcription because it's fairly straightforward.

34:20.570 --> 34:24.870
All it is, is recording what is written out on the command line.

34:25.210 --> 34:27.350
And it doesn't include... that's all it includes.

34:27.350 --> 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.

34:36.190 --> 34:39.710
And they say the unique data is recorded by each source.

34:39.750 --> 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.

34:48.590 --> 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.

34:58.430 --> 35:01.170
And module logging only buys you some.

35:01.170 --> 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.

35:15.050 --> 35:20.270
And then module logging is basically impossible to hit unobfuscated.

35:20.270 --> 35:25.130
So it provides much better insight, in my opinion, but does produce a whole bunch of data.

35:25.130 --> 35:28.730
And because events are individual, correlating them becomes harder.

35:29.010 --> 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.

35:38.810 --> 35:44.650
We'll go over a little bit of AMSI bypasses, some obfuscation, like standard obfuscation.

35:44.650 --> 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.

35:57.790 --> 36:03.290
We'll talk a little bit about script block logging bypasses and then event tracing bypasses.

36:03.290 --> 36:05.910
Those will be primarily in the demo.

36:07.250 --> 36:09.390
So reflective bypass.

36:09.390 --> 36:12.390
It's the simplest bypass that currently works.

36:12.390 --> 36:18.130
It grabs the systemmanagement.automation.amsi.utils.dll.

36:18.130 --> 36:24.850
It grabs a reference to it and then changes a field that says AMSI init failed and sets it to true.

36:24.850 --> 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.

36:50.530 --> 36:56.290
So when we're reflectively setting this field, we're saying that the initialization of AMSI failed.

36:56.290 --> 37:01.930
So just go ahead and return a clean finding regardless of what was actually done.

37:02.190 --> 37:04.070
And it doesn't even bother scanning the code.

37:04.070 --> 37:06.170
It just says there's something broken with AMSI.

37:06.170 --> 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.

37:14.810 --> 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.

37:23.170 --> 37:30.570
So a more complicated bypass we can look at, and there's a bunch of different implementations floating around.

37:30.570 --> 37:37.210
This is one I wrote based off of Tal Lieberman's work that he published at BlackHat.

37:37.510 --> 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.

37:51.490 --> 38:00.870
So this is using some a C-sharp to export DOL functions to allow us to access some areas of memory.

38:01.410 --> 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.

38:13.370 --> 38:16.510
And if it's over x amount, that's considered bad.

38:16.510 --> 38:21.390
If it's under x amount, then it's considered mostly good.

38:21.390 --> 38:23.510
And if it's a zero, it's considered good.

38:23.510 --> 38:26.150
Basically, you never see zero returned in real life.

38:26.150 --> 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.

38:35.990 --> 38:39.870
There's actually a couple others for policy implementation issues.

38:39.870 --> 38:44.750
But those are the three returns if it's just scanning your code without outside influence.

38:44.750 --> 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.

38:53.810 --> 39:02.610
It says just return a good value from the comparison and say that the script is fine.

39:02.610 --> 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.

39:13.470 --> 39:15.270
We can modify it however we please.

39:15.270 --> 39:22.050
And so the reflective DLL tells AMSI to return a clean result prior to scanning it.

39:22.050 --> 39:26.570
And as I mentioned, the patched one tells it to return after it being scanned.

39:28.350 --> 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.

39:39.310 --> 39:42.970
It's still very, very effective, but it does come with some costs.

39:42.970 --> 39:45.250
One of those being the complexity of your payload.

39:45.250 --> 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.

39:51.090 --> 39:56.730
You may be encoding it on top of changing variable names and splitting things up.

39:56.790 --> 40:03.030
So you can easily exceed limits that are put in place by PowerShell on the size of a command.

40:03.030 --> 40:05.250
It also takes a lot of time to be able to encode these.

40:05.250 --> 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.

40:12.570 --> 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.

40:17.670 --> 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.

40:32.870 --> 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.

40:39.730 --> 40:47.090
Here's just an example of some unobfuscated and obfuscated code for a launcher for Empire.

40:47.410 --> 40:52.190
The left one just shows the basic payload without any obfuscation in it.

40:52.190 --> 40:57.190
The right one has just the standard token all obfuscation set in place.

40:57.270 --> 41:00.190
And what it does, you can see here, it starts breaking things up.

41:00.190 --> 41:01.810
It starts encoding things.

41:01.810 --> 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.

41:07.830 --> 41:10.750
I'm sure Hubble will want to chime in a little bit on that.

41:10.750 --> 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.

41:20.690 --> 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.

41:34.450 --> 41:36.910
And it has kind of two issues.

41:36.910 --> 41:38.050
One, it's pseudo-random.

41:38.050 --> 41:41.930
At this point, invoke obfuscation has been out for a very long time.

41:42.250 --> 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.

41:50.750 --> 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.

41:56.590 --> 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.

42:10.750 --> 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.

42:18.930 --> 42:22.590
So some of these things work better if you run them in specific orders.

42:22.590 --> 42:26.490
And invoke obfuscation's token all doesn't always do that.

42:26.490 --> 42:28.410
So that's just some of the limitations on it.

42:28.410 --> 42:34.050
And just having those custom cocktails of different obfuscation techniques make a big difference.

42:34.050 --> 42:39.030
I know we have a couple that we keep for ourselves that seem to work almost all the time.

42:40.650 --> 42:44.590
So the obfuscation really does get you about 90% of the way there.

42:44.590 --> 42:48.970
Like I said, those custom cocktails that we have really do get us most of the way there.

42:48.970 --> 42:52.370
But there's some things that you just can't get rid of when you're obfuscating.

42:52.370 --> 42:58.670
And those are just like those common signatures that require you to restructure the code or eliminate certain keywords.

42:58.670 --> 43:04.450
One of the really good examples was something that we saw last year with the original Empire project.

43:04.450 --> 43:11.550
Prior to version 3, there was actually a mistake inside of the code where it double appended one of the headers.

43:11.710 --> 43:16.550
This allowed signatures to be based off of that issue, because it couldn't be obfuscated away.

43:16.750 --> 43:22.070
So any virus and AMSI and everything was detecting off of this specific mistake in the code.

43:22.070 --> 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.

43:30.190 --> 43:36.510
So really, that restructuring and making sure that those signatures are broken is really, really important.

43:36.590 --> 43:42.570
So now we're going to talk a little bit more about what we kind of call keyword aliasing.

43:42.730 --> 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.

43:53.730 --> 43:57.390
And these can be triggered even when not ran directly by AMSI.

43:57.390 --> 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.

44:08.550 --> 44:13.890
So then it starts searching strings in memory, or Defender starts searching for strings in memory.

44:13.890 --> 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.

44:23.190 --> 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.

44:38.090 --> 44:46.450
Some of these strings to keep in mind are actually invokeMimikatz, invokeEmpire, powersploit.

44:47.010 --> 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.

45:03.430 --> 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.

45:13.430 --> 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.

45:22.710 --> 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.

45:32.230 --> 45:34.790
It just becomes that is the value that we are using.

45:34.790 --> 45:45.850
So in the example over on the right, we're changing InvokeMemeCats to QAD45 and InvokeEmpire to DLXZ9.

45:45.970 --> 45:48.250
This is how it's done in Empire now.

45:48.250 --> 45:52.650
On startup, it automatically makes entries to obfuscate those strings.

45:52.650 --> 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?

46:08.090 --> 46:17.390
You could make these something like InvokeFileSearcher, InvokeOrganizer, so that it would look even less suspicious than just a random string.

46:17.390 --> 46:20.690
We don't do this to everything for a couple of reasons.

46:21.510 --> 46:25.650
You could do it, but it's time consuming to pick which values to alias.

46:25.650 --> 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.

46:36.210 --> 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,

46:51.010 --> 46:52.030
then your stuff's going to break.

46:52.030 --> 46:54.630
So there's just some complexity added in the aliasing.

46:54.630 --> 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.

47:02.810 --> 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.

47:12.530 --> 47:18.750
You can actually import to avoid script logs, as well as the transcription log as well.

47:18.750 --> 47:21.510
ImportAlias is the one I've been playing with the most.

47:21.510 --> 47:28.170
What happens is, when we import our aliases, for those that don't know, let me take a step back.

47:28.170 --> 47:36.090
Aliasing, in terms of PowerShell, allows us to set whatever function name we want for any commandlet.

47:36.090 --> 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.

47:49.170 --> 47:57.490
And then, whenever you type in print into PowerShell, it knows that that is the same as doing get printer.

47:58.890 --> 48:02.970
You can then save those aliases using ExportAlias.

48:03.390 --> 48:13.570
And then, when you import alias, those terms and different names for your commandlets never get seen by the log.

48:13.570 --> 48:15.690
They just get imported into memory.

48:15.690 --> 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.

48:22.110 --> 48:24.090
It'll see print instead of get printer.

48:24.310 --> 48:30.990
If you have module logging enabled, then it will still see the module you're using.

48:31.290 --> 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.

48:41.170 --> 48:45.670
But as we said, it's basically impossible to avoid hitting the module logging initially.

48:47.570 --> 48:51.430
So, this is kind of what it looks like to change things up.

48:51.430 --> 48:57.270
On the right is if I want to do InvokeExpressionNewObjectSystem.net.webClient.

48:57.450 --> 48:58.830
That's what it would look like.

48:58.830 --> 49:01.410
That's what it would look like in the logs.

49:01.410 --> 49:05.670
Instead, to run that, I went and did some aliasing by hand.

49:07.170 --> 49:11.810
And we can embed further commands into the alias description.

49:11.810 --> 49:21.130
And if you look at the import.alias.csv, that imported all of my alias commands.

49:21.130 --> 49:30.350
Now I run this completely nonsensical command to someone looking at it that says I parentheses ca.description.

49:30.970 --> 49:37.510
And then that caused another execution that was bcb.description.

49:37.930 --> 49:44.350
So, in this case, I was was InvokeExpression.

49:44.350 --> 49:47.290
And b was that new object.

49:47.290 --> 49:52.030
And then the description for new object was system.net.webClient.

49:52.030 --> 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.

50:03.250 --> 50:07.990
Because as soon as you close the PowerShell session, the aliasing is gone.

50:07.990 --> 50:11.950
It is not saved saved permanently anywhere.

50:11.950 --> 50:12.930
So, you have to import.

50:12.930 --> 50:18.470
If you want to use aliases consistently, you have to import them each time you start a new PowerShell session.

50:18.470 --> 50:20.710
That's why the function was built.

50:20.710 --> 50:25.350
So, as soon as we kill our PowerShell session, our aliasing is gone.

50:25.350 --> 50:29.170
And the key to what the script block log means is gone as well.

50:29.530 --> 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.

50:51.250 --> 50:58.230
First things first, how you get to the operational log for PowerShell is you're going to use event viewer.

50:58.370 --> 51:01.410
You're going to come down here and type in event viewer.

51:01.410 --> 51:03.430
You want to make sure you run it as an administrator.

51:03.430 --> 51:08.230
That just makes it easier to clear the logs when you're testing that kind of stuff.

51:08.230 --> 51:11.050
But you can't usually view it even as an unprivileged user.

51:11.050 --> 51:12.650
You just can't modify it.

51:12.670 --> 51:26.470
You'll then click on Microsoft, then Windows, then come down here to PowerShell, open PowerShell, and then click on operational.

51:26.470 --> 51:31.510
Right now I cleared the logs prior to starting this so that we can make it easier to see everything.

51:32.010 --> 51:40.290
So, if I go ahead and click on PowerShell and open it, it's actually just starting PowerShell generates some logs.

51:43.050 --> 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.

51:50.290 --> 51:52.150
So, if I refresh it again, we should get a few more.

51:52.150 --> 51:53.250
Yeah, there we go.

51:53.690 --> 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.

52:02.390 --> 52:08.890
Then we'll see this strict mode that gets used throughout when you're running PowerShell.

52:08.910 --> 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.

52:18.190 --> 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.

52:32.230 --> 52:35.750
As I said, prompt comes up after every execution.

52:36.010 --> 52:41.510
But if we go down here, we can see this right host test for our script block log in 4104.

52:42.230 --> 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.

52:55.590 --> 52:59.350
So, now we're going to go over here, now that we've seen that.

53:00.130 --> 53:04.350
And the first one we're going to talk about real quick is script block logging.

53:04.350 --> 53:07.170
This was published by Matt Graber.

53:07.170 --> 53:14.230
It's got a few modifications from his original one, but this comes from a default Empire implementation.

53:14.230 --> 53:23.130
All it's doing is it's creating a new dictionary that gets added to our cache group policy settings.

53:23.130 --> 53:29.130
We access that reflectively, and we're just telling it that script block logging has been turned off when it goes.

53:29.130 --> 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.

53:37.690 --> 53:44.590
We're able to do this because, just like the AMD bypass, this is all in our process memory.

53:44.590 --> 53:46.670
So, we have complete access to it.

53:46.670 --> 53:50.250
We can manipulate in essentially whatever way we want.

53:51.290 --> 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.

54:02.130 --> 54:07.330
So, all of that code that we just ran is going to hit our script block logging.

54:08.230 --> 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.

54:15.210 --> 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.

54:23.110 --> 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.

54:30.730 --> 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.

54:43.090 --> 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.

55:02.770 --> 55:07.710
So now, the other nice part about this is that only affects our local process.

55:07.710 --> 55:14.810
So, if I just close out PowerShell and clear our logs, we will reset everything.

55:15.370 --> 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.

55:32.870 --> 55:35.210
It just never really got a lot of traction.

55:35.890 --> 55:38.950
It's, I believe it's linked in our slides.

55:38.950 --> 55:42.730
If not, I have the link for everyone that I can share.

55:42.990 --> 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.

55:54.710 --> 55:58.950
But instead, we're disabling event tracing, which happens at a lower level.

55:58.950 --> 56:04.090
This event tracing actually disables our module logging as well.

56:04.390 --> 56:11.150
So we run this, and we go look at our logs.

56:13.110 --> 56:15.390
And we'll see that we get a warning level event.

56:15.390 --> 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.

56:35.630 --> 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.

56:44.190 --> 56:45.990
And if we go run that

56:49.330 --> 56:56.190
right host test again, we can see that we have had produced no logs.

56:56.190 --> 57:01.690
So we still have viable ways of totally disabling PowerShell logging.

57:01.790 --> 57:06.350
And like I said, there are ways to get this down, so it won't produce a warning level event.

57:06.770 --> 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.

57:12.830 --> 57:14.530
I was just going to show it to you real time.

57:14.530 --> 57:17.710
So we'll go ahead and clear the log.

57:20.630 --> 57:23.210
Open PowerShell back up again.

57:27.010 --> 57:31.110
We're just going to go ahead and import our alias.csv.

57:33.210 --> 57:37.270
I'm going to go ahead and run this nonsensical looking thing.

57:37.270 --> 57:45.230
As we can see, it gives us an output that a new web request object was created.

57:45.250 --> 57:47.130
So now when we go look at our logging,

57:52.030 --> 57:56.110
we can see a couple of different script block logs were called.

57:56.110 --> 58:01.310
So I called this ICA.description initially.

58:01.790 --> 58:05.750
And this is where we can see that it's still hitting our module logging.

58:05.750 --> 58:08.390
Even the script block logging can't see it.

58:08.570 --> 58:18.870
It appears that C is aliased to get command, as we can see here.

58:18.870 --> 58:19.990
I'm looking through that.

58:19.990 --> 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.

58:29.830 --> 58:33.390
So we have this value A that gets passed to it.

58:33.390 --> 58:40.570
Then we see it execute this bcb.description, which again is a git command.

58:40.730 --> 58:48.910
And then we also see that we're executing a new object that was being passed a system.net web client.

58:49.450 --> 58:55.590
And so that just shows you module logging is kind of effective at bypassing this import aliasing thing.

58:55.590 --> 59:01.730
But the import aliasing totally obfuscates logs in a way that you can't really undo it.

59:01.770 --> 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.

59:10.190 --> 59:15.550
So when we close out PowerShell, all of our aliasing key is gone, so they can't go look it up.

59:15.730 --> 59:19.410
So it's just another level of obfuscation.

59:19.410 --> 59:22.510
And it also makes it really hard for Amzie to see what's going on.

59:22.510 --> 59:25.090
So that's just something kind of fun to play with.

59:25.110 --> 59:26.290
But that's all I got.

59:26.290 --> 59:28.850
So I'll toss it back over to Anthony.

59:28.850 --> 59:30.830
And we should have just a little bit of time left.

59:30.990 --> 59:33.730
Thanks for having us at the Red Team Village.

59:33.730 --> 59:36.010
We're going to be in the channel for a little bit to answer any questions.

