email info@BC-Security.org

Top Categories

Spotlight

todayOctober 10, 2024

Offensive Security Tools Cx01N

Not Your Grandfather’s Empire

Not Your Grandfather’s Empire I’ve wanted to put this blog together since returning home from DEFCON. Anytime we ran into someone who recognized our swag, they mentioned how much they loved Empire back in the day and didn’t realize it was being actively maintained. This made me reflect on all [...]


PowerShell Logging: Obfuscation and Some New(ish) Bypasses Part 2

Cyber Security Hubbl3 todayAugust 25, 2020 3613 2 5

Background
share close

In Part One of this series, we went through several ways of disabling Module Logging, as well as an alternative means of disabling ScriptBlock Logging. This entry will focus on the obfuscation of the PowerShell Script in the ScriptBlock log and Transcription log. First, there will be a little more discussion on a module log bypass technique because we can also use it to create some obfuscation!

In Part One, one of the ways of discussed to circumvent module logging was to create a referenceable object to the implementing type like this:

$Cmd = [System.Management.Automation.CmdletInfo]::new("Write-Host", [Microsoft.PowerShell.Commands.WriteHostCommand])

I mentioned that you have to execute by either using & or Invoke-Command, which created a pretty big indicator of this technique. There is actually a way to use it without those, you just have to put it into the session cmdlet table. I’ll save y’all the trouble of spending several days figuring out how to register a single cmdletinfo object from memory and doesn’t work with import-module. It turns out there isn’t a super straightforward way to do this. However, we can use reflection magic to access the cmdlet table that PowerShell builds at startup. To get access to it, use the following commands below:

$ssInternal = [System.Management.Automation.SessionState].GetProperty('Internal', @('nonpublic','instance')).GetValue($ExecutionContext.SessionState)
$currScope = $ssInternal.GetType().GetProperty('CurrentScope',@('nonpublic','instance')).GetValue($ssInternal)
$cmdletTable = $currScope.gettype().GetProperty('CmdletTable', @('nonpublic','instance')).GetValue($currScope)

From here, either add the cmdletinfo object to a new key or replace the existing key. I like to replace the existing key. Doing a get-command before and after, you can see that a number of the fields are no longer populated. 

Before:

After:

We could automate this process to replace every function or just unhook the ones we need. This also provides the option for creating some really confusing obfuscation that can be mixed in with the commands. We can also use this to break the AMSI signatures. Since all the commands will now vary and can have any arbitrary name that won’t be unwound by AMSI.  (Theoretically, AMSI could inspect the implementing type of the command to check for this kind of thing, but I have not found that to be the case)

Obfuscating Logs Through Import-Alias

So there is actually a less thorough but easier way of obfuscating which command is being used that AMSI won’t unwind and that is Import-Alias. You may have used Set-Alias previously in your PowerShell endeavors, which lets you set an alias for any command in PowerShell, as the name implies. Import-Alias lets you import aliases from a CSV so that you can save them for use between sessions. If you investigate the logs while using it, there are a couple of interesting things that you may notice. The first is that the ScriptBlock log doesn’t unwind aliases:

The second thing is that Import-Alias does not leave any logs as to what aliases have been set:

What’s nice about this is that the aliases are only set for the session, so once it’s closed, the aliases are gone. This seems pretty cool, but we still have to drop a CSV to disk that contains all our aliases, right? Well, in fact, we do not. Import-Alias supports WebDAV! So if we can make a WebDAV connection, we never have to hit the disk. WebDAV, of course, comes with its own set of indicators, and I leave it up to the reader to decide if the opsec risks are worthwhile or not.

If you decide WebDAV is acceptable, you can also use Import-Alias as a download cradle. When setting an alias, a Description field can be set and then the string retrieved with (get-command <cmd>).Description is then executed either by creating a new ScriptBlock or using IEX. You could always alias get-command to further obfuscate the log.

One shortcoming of this method is that it doesn’t do anything to obfuscate module logging. As of now, I am unaware of any way to obfuscate Module Logging. As was discussed in Part One, there are several ways to disable it outright, but I’ve yet to see a method that allows for actual obfuscation of the log.

Using this with Empire and Keywords

So both of these methods for obfuscating the ScriptBlock log are pretty useful, but how do you use them with your pre-built Powershell scripts? Going in and replacing terms would be time intensive and has to be redone every time you want to update the obfuscation. It also means you have to update it anytime you make changes to the base script to improve functionality. Luckily, Empire has a function built into it for exactly this purpose! The keyword option was added to Empire’s main menu back in July and was designed with this type of use exactly in mind. We can add a random value to replace a designated string like this:

Keyword has two options. The first shown is to provide the string you are targeting and then the replacement value. You can also provide the target string and Empire will generate a random value to replace it with. The first is more useful in combining with our command name obfuscation. As of now, you have to enter each value manually, but you could build a resource file that would automatically load in all your obfuscation pairings.

So now that we have all these various tools, what are the best ways to utilize them? Personally, I sometimes find it valuable to not always completely disable logs. By leaving a nonsensical log or one with misleading looking commands, we can send the defenders in the wrong direction. This is especially useful if we don’t think that we will be able to operate completely undetected. If the defenders are going to investigate the box, either way, leaving some logs can look less suspicious then leaving no logs. Or use these as a way to mix up download cradles and how you disable logging. As I said in Part One, you can never have too many options for obfuscation.

If you enjoyed this material and would like to learn more about Red Teaming and APT emulation, check out our upcoming course in November. Use Promo Code HACKTOBER for $100 off ( Expires after 16 Oct 2020)

Written by: Hubbl3

Tagged as: .

Rate it

Previous post