Binary Pulsar

技術寄りなセキュリティの話題について書きます

ReflectionによりPowerShellでWindows APIを呼び出す手法

概要

近年盛んであるPowerShellを悪用した攻撃の根幹を成す技術の一つが、PowerShellによるWindows APIプログラミングであることは間違いないでしょう。PowerShellではその豊富な機能により、Windows APIを複数の手法で呼び出すことが可能であるため、カーネルエクスプロイトやメモリ上の機密情報の取得などが可能です。本記事では、Windows APIの呼び出しを可能とする技法のひとつである、Reflectionという機能を用いたWindows APIの呼び出し手法を取り上げます。

PowerShellとReflection

Reflectionは情報工学における技術の一つであり、プログラミングにおいては「自分自身の構造を書き換える機能」を指します。PowerShellにもReflectionが機能として実装されており、Reflectionにより新たな型を定義したりプログラム内部の情報を参照することが可能です。

PSReflect

Reflectionを活用してWindows APIを呼び出すためのPowerShellスクリプトが、Matt Graeber氏によって公開されています。

github.com

スクリプトの詳細についてブログの一記事としてまとめるにはなかなか骨が折れるため、詳細は割愛します。

PSReflectの機能は以上に公開されているスクリプトのうち、PSReflect.psm1に実装されています。スクリプトには様々な関数が実装されていますが、明示的に使う関数はNew-InMemoryModule関数とAdd-Win32Type関数の2つのみです。New-InMemoryModule関数はメモリ空間にモジュールを新たに定義する関数です。Add-Win32Type関数は、New-InMemoryModule関数により定義されたモジュールを用いて、ReflectionによりWindows APIPowerShellに追加する機能を持つ関数です。

PSReflectを利用してWindows APIを呼び出す

それではPSReflectを用いてWindows APIを呼び出す手順を示します。本記事ではuser32.dllに実装されているMessageBox関数を取り上げて、Windows APIを呼び出す手順を示します。

実践に移る前に、MessageBox関数というWindows APIの実装を調べましょう。Windows APIの多くはMicrosoft公式Webサイトに、公式文書として実装を参照することが可能です。(公式文書として公開されていないUndocumented APIと呼ばれているWindows APIが存在しますが、本記事の内容を超えるため触れません。)Microsoftの公式文書は様々な国の言語で公開されています。本記事では英語に馴染みがない読者を想定して、日本語版がある公式文書に関しては日本語版の公式文書のリンクを掲載しますが、言語である英語が最も情報の更新が早く情報が充実しているため、可能であれば英語版を読むべきでしょう。MessageBox関数の公式文書は以下のWebサイトに公開されています。

MessageBox 関数

MessageBox関数の実装は以下の通りです。

int MessageBox(
  HWND    hWnd,
  LPCTSTR lpText,
  LPCTSTR lpCaption,
  UINT    uType
);

Windows APIの関数を利用するには、それぞれの引数の意味とその型をどの型として定義すればよいかを理解する必要があります。以上に記載のWindows API関数の公式文書の内容では、引数の型がC#PowerShellでのプログラミングとは異なるため、それぞれ対応する方に置き換える必要があります。Windows API関数の公式文書に記載の型と、C#PowerShellでのプログラミングにおける型との対応に関しては、以下のMicrosoft公式文書に記載されています。

プラットフォーム呼び出しによるデータのマーシャリング | Microsoft Docs

公式文書によると、HWND型はハンドルを指定する引数の型であるためSystem.IntPtr型に対応します。LPCTSTR型はSystem.String型またはSystem.Text.StringBuilder型であるため、本記事ではSystem.String型を採用します。UINT型はSystem.UInt32型に対応します。 それではMessageBox関数の引数について解説しましょう。まず、第一引数のhWndですが、メッセージボックスを立ち上げるプロセスのハンドルを整数の数値で指定する引数です。親プロセスとして立ち上げる場合は0を指定します。次に、第二引数のlpTextですが、この引数にはメッセージボックスに表示する文言を文字列型の引数として指定する引数です。第三引数のlpCaptionはメッセージボックスのキャプションの文言を指定する引数であり、第二引数と同じく文字列型の値をしてします。最後に、第四引数のuTypeですが、この引数には「メッセージボックスの書式を指定する整数」を指定します。メッセージボックスの書式については、先述のMessageBox関数の公式文書に記載されています。例えばuTypeを「2」と指定すると「YesとNoとIgnoreが選択肢として表示されるメッセージボックス」が、「4」と指定すると「YesとNoが選択肢として表示されるメッセージボックス」が表示されます。

まずはPSReflect.psm1から、スクリプトに定義されている関数をインポートします。

PS C:\> Import-Module .\PSReflect.psm1
PS C:\>

続けて、PSReflect.psm1からインポートしたNew-InMemoryModule関数により、PowerShellのメモリ空間にモジュールを定義します。ModuleNameオプションに任意の名前を値として与えてNew-InMemoryModule関数を実行することにより、任意の名前のモジュールを定義することが可能です。本記事ではモジュール名をWinApiとして、変数Moduleに定義します。

PS C:\> $Module = New-InMemoryModule -ModuleName WinApi
PS C:\>

次に型情報を配列型の変数として定義します。関数毎に配列が多変数の一要素として、以下の書式で定義します。

(func <DLL名> <Windows API関数名> (<返り値の型>) @(<第一引数の型>, <第二引数の型>, ...))

MessageBox関数の場合は、例として以下のように変数Funcdefに定義します。

PS C:\> $Fundef = @( (func user32 MessageBox ([int]) @([IntPtr], [String], [String], [int]) ) )
PS C:\>

関数の型情報を定義したら、Add-Win32Type関数によりWindows APIを読み込みます。Add-Win32Type関数のModuleオプションに先ほどNew-InMemoryModule関数で定義したモジュールを、Namespaceオプションには任意の名前で名前空間を設定します。本記事の例では、名前空間の名前をWinDLLとして、Windows APIの読み込みを変数Typesに定義します。

PS C:\> $Types = $Fundef | Add-Win32Type -Module $Module -Namespace 'WinDLL'
PS C:\>

続けて、変数Typesでの定義で読み込んだWindows APIから、利用したDLLの名前を指定します。今回の例として取り上げているMessageBox関数というWindows APIは、user32.dllに実装されているため、以下のようにして変数User32に定義します。

PS C:\> $User32 = $Types['user32']
PS C:\>

最後に、変数User32に定義したuser32.dllを読み込んだ空間からMessageBox関数を呼び出すことにより、メッセージボックスを起動することが可能です。

PS C:\> $User32::MessageBox(0, 'Hello, world!', 'PopUp', 2) | Out-Null
PS C:\>

以下の図に例を示します。

f:id:binary-pulsar:20181003120256p:plain

まとめ

本記事では、近年のPowerShellの攻撃で用いられている根幹をなす技術である、Windows APIの呼び出しの手法の一つを取り上げました。Windows APIの呼び出しについてはその他にも複数の手法が存在し、いずれの手法も攻撃スクリプトに活用されています。その他の手法によるWindows APIの呼び出しについては、またの機会に取り上げます。

PowerShellの難読化解除

概要

情報セキュリティ技術者の実際の業務では、文書ファイルなどに添付された、難読化されたPowerShellスクリプトを解析するということが、担当業務によってはあると考えられます。過去3回の記事ではスクリプトを難読化する手法について解説してきました。原理が一通り分かったところで、PowerShellスクリプトの難読化を解除する手順を解説しましょう。

着目する点

実際の情報セキュリティ対策業務では、標的型メールなどに添付されたMicrosoft Officeなどに埋め込まれた、難読化されたPowerShellを解析する場合があるでしょう。解析の際に誤って、そのような難読化されたPowerShellスクリプトを実行してしまうと、取り返しがつかない損害が発生してしまう危険性があります。よって、PowerShellの難読化を解除するには「PowerShellを実行する箇所を発見し取り除くこと」が重要です。 過去3回の記事をまとめると、難読化されたPowerShellのコードを実行するものは、以下の要素であることがわかるでしょう。

アンパサンド記号とドット記号を除き、難読化された状態で埋め込まれている可能性があるため、注意が必要です。難読化されたPowerShellスクリプトの難読化を解除しようという場合は、以上の要素を漏れなく確認し、取り除くことが望ましいでしょう。

難読化解除の基本方針

難読化されたPowerShellの実行に必要となる要素が把握できたらあとは簡単です。残された部分をPowerShellのコンソールや、PowerShell ISEでそのまま実行すれば、難読化される前のスクリプトがそのまま出力されます。 例えば、過去の記事で作成した以下のスクリプトを例にしましょう。

(((102, 111, 114, 101, 97, 99, 104, 40, 36, 105, 32, 105, 110, 32, 40, 49, 46, 46, 53, 41, 41, 123, 32, 87, 114, 105, 116, 101, 45, 72, 111, 115, 116, 32, 36, 105, 125) | %{ ([Int]$_ -as [char]) }) -Join '') | &($env:comspec[4,15,25] -Join '')

スクリプトの終端近くに、アンパサンド記号がついていることが確認できます。過去の記事で開設した通り、アンパサンド記号はコマンドレットや実行ファイルを実行するために用いられます。よって、アンパサンド記号でくくられている文字列が、Invoke-Expressionやiexに相当するものであることが予想できるでしょう。実際に、アンパサンド記号直後に括弧で括られている文字列をPowerShellのコンソールに張り付けて実行すると、以下のように「iex」という文字列が出力されることがわかります。よって、パイプ文字以後の部分がInvoke-Expressionコマンドレットに相当するということがわかります。

PS C:\> $env:comspec[4,15,25] -Join ''
Iex
PS C:\>

あとはアンパサンド記号直前のパイプ文字以後の部分を取り除き、コピーしてPowerShellに貼り付けて実行すれば、難読化されたPowerShellで実行されようとしているスクリプトが出力されます。

PS C:\> (((102, 111, 114, 101, 97, 99, 104, 40, 36, 105, 32, 105, 110, 32, 40, 49, 46, 46, 53, 41, 41, 123, 32, 87, 114, 105, 116, 101, 45, 72, 111, 115, 116, 32, 36, 105, 125) | %{ ([Int]$_ -as [char]) }) -Join '')
foreach($i in (1..5)){ Write-Host $i}
PS C:\>

よって、以上の難読化されたPowerShellで実行されるスクリプトforeach($i in (1..5)){ Write-Host $i}であることがわかります。

難読化解除の例

それではもう少し難しい例を用いて、難読化解除の手順を説明しましょう。本記事で難読化解除の対象として取り上げる難読化されたPowerShellスクリプトを以下に示します。

& ((GEt-variabLe '*MDR*').Name[3,11,2]-JOIN'') ( ( '70P6fZ77X65Z72o73Z68Z65Z6cX6cM2eP65X78Z65<20X2do65<6eX63Y20Y4bo41l41l6eY41X48l34l41<4aZ77Z42<38X41l43P55X41Z49l41P41Z67P41Y48P73o41M49X41o41Y67X41Z43M51M41P65l77<41X6aP41<43M4do41o49P77X41l6a<41o43l4do41M49<77<41<6aY41<43M4dM41l49X77P41Y6ao41o48o30<41<49X41<41M67X41l44Y30P41o4bY77Y41X6bo41M43Z67o41X49<41M41Y67X41X43Y6bM41l66<51o42M37Y41o43o41M41Z49Y41<41Z6bP41M48o73Y41o49Y77M41P6aP41Y43l4dX41Y49M77l42o39Z41M43<41<41<49Z41Y41P39l41l43<51Z41Y65<77X41X6aY41P43l4dY41X49o77o41Y6a<41M43M4dM41P49<77Y41l6a<41<43M4do41o49Z77<41X6aY41Z48o30X41X49Z41P41<67l41<48Y30Y41l65Y77P41X67o41P43M41P41l4aY41P42<37X41M43o4d<41<49l77X41<6aM41<43o4dP41X49l77l41l6aM41P43l4dZ41Z66M51X41<39Z41o43Y73Z41X4bo77X41M6bZ41P48o73M41P49Y77X41Z6al41Y43Z4dM41P49l77P41Z6ao41X43X4do41P49M77o41M6aP41Y43Z4d<41Z49o77<42l39Y41M43Z41Y41X49Z41Y42Y39M41Y48o73P41o49P41Y41M67M41Z43Y51M41<65P77o41Z6aP41<43<4dX41X49<77Z41<6aY41o43Y4dM41o66l51Y41P67<41Y43M41Y41M50l51<41<67<41X43Z41<41Z4bX41Z41l67Z41<43P41o41Y4aX41Z42X37M41o43l4dX41Z49o77M41X6aM41l43M4dl41X49l77P41Y6aX41l43X4dP41Z49o77<41X6al41Y43o4dZ41X66<51<41X67X41<43o41l41l50M51l41X6b<41<48Y73M41l49l77P41Y6ao41P43P4dY41<49X77l41o6a<41X43P4d<41o49<77X41<6aP41<43M4do41M49Y77l42Z39o41<43M73l41X49o41<41l67X41Z43X51Z41o65Z77o41<6aP41l43<4dl41X49<77o41l6aP41<43X4d<41o49<77Z41Y6ao41P48o30Z41Z4b<51P42l39X41Z43<41P41l49Y41<42Y37o41Z43M41o41l49Y41<41Y6bY41<48P73Z41l49o77Z41M6al41M43<4dM41P66l51l41Z39M41M43Y41P41<49Z41P41l6fM41X43P41<41l49o41<41X6bY41o48M73<41P49Y77<41<6aM41Y43X4dY41Z49Z77l41<6a<41Y43P4dY41M49l77Z41P6aY41l43P4dZ41l49Z77M42l39l41o43M41<41o49P41Y41l39M41M43o51P41l65<77X41X6aY41<43<4dY41M49o77P41<6aM41<43l4dY41Y49X77<41o6aM41o43P4dl41l49l77o41<6a<41Z48M30l41l49P41X41M67Y41<43P73X41l4aY41Z42X37o41l43o4dY41X49Y77o41Z6aM41<43M4dM41l49l77M41X6aX41Z43Z4dl41X66Y51Z41<70<41l48<30o41l49X41l41<67Y41<48l73M41l49M41Z41Z67o41o43o51o41M65X77o41P6aP41M43l4dl41Y49l77Y41P6aY41P43Z4do41l49P77P41X6aP41P43P4d<41X49l77<42Z39l41X43P41Y41<49M41M41l39P41l43Z41l41o49P41<41<6fP41X43Y51<41Z65P77Y41Z6al41M43M4dP41<49<77P41Z6al41l43<4d<41l49<77l41Z6al41o43<4do41M49o77<41M6ao41M48P30Y41M49<41Z41Y67P41Y44M30X41l49Y41l41X67Z41l43X51Y41P65l77Z41o6aM41Z43M4dl41M49X77Z41Z6aP41l43P4dY41M49Z77o41Y6a<41Z43l4do41o49o77M41l6ao41Z48<30o41Y49P41M41Z67<41<43Z73<41l49o41M41P67P41X43<51Y41Y65o77Z41Z6ao41Y43l4dM41l49l77o41M6aM41o43P4dl41o49M77o41o6a<41X48l30M41P49Z41P41X67<41Y43Y6bY41o66Z51o41l67<41M43<41o41Z65Y77P41l6bX41M48Y73P41P49o77Z41Y6al41Y43X4dX41l49P77<41X6a<41<43Z4d<41l49Z77Y41o6al41Z43P4dP41o49Z77M41o6aZ41M43<4dZ41Y66M51X41Z67X41l43<41X41Z50l51X41Z67X41X43Y41l41o4bZ41l41X6bP41Y48Z73l41M49X77X41M6aZ41l43o4d<41M49l77o41l6aY41Y43P4dY41Y49l77Z41P6aX41M43P4dl41X49Z77P42<39<41Z44o30o41o4al41M42Z37Y41<43l4dM41Z49Y77X41Y6a<41X43M4dX41X49o77l41Z6aY41o43X4do41o49o77X41l6al41P43X4dl41Z66Z51Z41o72o41Z43Y51P41X65Y77l41P6aM41Z43l4dX41<49<77X41Z6ao41P43l4dP41P49M77o41M6aX41M48M30l41M49o41M41<67o41o43X6bl41X66M51Z41Y67P41X43P41o41Y65M77Z41X6bY41Z48X73M41X49l77o41P6aZ41l43M4dl41Z49Y77<41M6aP41l43Y4dX41Y49Y77M41P6ao41<48<30l41o49l41o41o67P41M44P30M41P49l41Z41M67X41o43o67X41<4ao41Y42l37Y41l43l4dZ41l49<77X41<6al41Z43Z4dZ41Y49o77Y41<6aP41P43l4dM41P49o77X41<6ao41M43X4dP41Z66o51l41Z39Y41o43M41Y41Y49Z41M41l6b<41Z48o73l41Y49X77X41X6aX41Y43M4d<41<49l77M41X6aM41P43o4do41<49l77Z41l6aX41X43X4d<41<49X77M42l39P41<43<73o41<4aX41P42Y37Y41Z43o4dX41<49<77Y41Z6aY41l43Y4do41X49l77X41Y6ao41M43l4dl41M66M51P41l67M41<43Z41P41P4bM51<41P67Z41<43Z41l41l66P51P42Y37Y41Y43X41Z41M49P41P41M6bP41P48<73M41o49<77o41l6aP41Z43l4dX41o49l77X41o6aM41X43Z4dX41l49X77<41M6aY41Z43<4dZ41Z49o77X41<6al41X48Y30Y41<49M41<41o67P41o44P30P41Z4b<41l41M67l41X43o41<41l4aX41l42M37l41o43P4dl41M49<77l41P6al41<43M4dl41P49Y77Z41<6ao41Y43<4dl41l49<77P41P6al41M43o4dZ41o66P51Z41<39o41M43Y41M41o49M41l41Z6b<41M48l73o41<49M77<41P6al41Y43M4dl41P49Z77P41M6aZ41<43P4do41l49P77X41X6aZ41M43P4dZ41X49<77M42P39P41o43l73Y41<49Z41P41l67o41P43X51l41l65P77<41X6aZ41Y43<4dY41l49l77Z41o6ao41Y43<4do41<49<77Y41Z6aP41l48<30<41P49Y41o41X67Z41o43Z6bl41l49<41Z41<67Z41l48M30M41Y65M77l41l6bl41P48Y73Y41<49X77o41o6aZ41l43o4dP41l49X77Z41<6aZ41<43P4d<41l66Z51M41Z67<41P43P41l41Y50l51X41<6fP41P43X51Y41<65l77o41o6ao41P43Z4dl41<49<77<41<6aM41Y43<4d<41X49M77o41Y6ao41<43Y4dZ41P49P77o41l6ao41Y48X30Y41l50P51M41Z67X41M43<41Y41l4ao41<42X37<41Z43Z4dY41X49P77<41Z6al41X43M4dl41P49Y77<41o6ao41X43<4dM41P49l77M41Y6aZ41P43P4dZ41l66M51o41Y67Y41l43M41Z41<4bP77M41Z6bP41<48P73o41P49l77X41l6aY41<43M4dZ41l49M77M41X6al41X43o4do41<49<77<42M39Y41l43P6bZ41o49P41Z41<67X41P48M30l41X65M77M41Z67M41<43l41X41<4aY41Z42Y37<41X43Y4dl41X49l77o42Y39<41P43X41<41Y49M41<41Y39o41X43Z67<41<4aX41X42X37o41P43o4dY41l49l77l41M6ao41l43P4dP41P49o77Y41X6aP41P43Y4dP41Z49l77Y41l6al41X43X4dl41X66P51Y41l39Y41M43X41M41X49Y41<41o6b<41Z48Z73o41l49M77o41M6al41P43Z4dX41M49<77Y41X6a<41<43M4dY41Y49Y77X41X6aY41<43<4do41l49M77X42Z39Y41M43<41Y41Z49o41P41Y72<41P43o41Y41<49l41<41Z6bP41P48Y73X41X49l77Z41<6aY41M43Y4dl41P49M77l41P6aX41M43M4dX41M49X77Z42M39Y41l43M41l41M49Z41Z41Y70<41M48M30<41X65<77Y41Z67Y41M43<41l41X4aZ41o42P37o41o43P4do41l66P51X41<67Z41M43Y41Y41Z50M51P41<67Z41o43<41X41Z49Y67M42o62X41<43<49Z41P49Z41P41o67X41l43M73l41l49P67<41l6bM41Y43o67Y41X49Z41Z41P67Z41Y45o41M41l65o77X41l67<41<43Z41Y41o66P51o41Z70o41P43P41<41M49P41o41X69l41X46M73o41<4aZ41Y42Z37Y41Z43P4dP41Z49o77X41M6ao41X43M4d<41Z49<77Y41Y6a<41P43o4dM41Y49o77M41M6a<41Z43l4dP41o49o77P42o39M41<46Z30P41Y4bZ77X41o69X41Y43M51<41o4b<41o42Y41M41M48<73P41o66<51M41l70Z41X43<49X41M57X77<41l67Z41Y43M41Z41o49o67Y41o6bM41o48l73<41M49<77Z41M6a<41P43<4dZ41<49l77M41Y6aX41X43Y4do41P49Y77M42o39M41P43Y51M41Z65l77X41X6ao41X43X4do41X66X51P41P69o41M43P41X41Z49o41X42X64<41l43P73X41<49X41P41l67P41o43Z49<41M4aZ41l41<6fo41o45l41<41X65Z77M41Z67X41M43X41o41M66Z51M41Z67Z41Y43Y41Z41M4bZ51l41P69X41P46<73<41l49Z41o41o67P41X43l49<41Y4aY41X42X37P41Z43Z4do41Z49o77P41Z6a<41Z43Y4dZ41Y49Z77o42<39Y41X43X51l41o65X77M41o6aY41X43X4dZ41P49Y77<41X6aY41l48Z30P41o49<67<42l64o41M43P73Y41l49<41<41Z67o41o43<49Z41Y4a<41M41o2fX41Z43l49P41Y57M77M41Y67X41Z43Y41Y41X4aM41M42Y37M41<43Y4dY41<49l77o41X6ao41o43X4dl41l49<77o41P6aY41<43Z4dM41<66Y51P41X67X41X43l41l41l58<51Z41Z67X41<43Y41P41Y4bo77o41o67l41<43l41Z41o49M67Z42X64Z41<43Z49X41Y49M41l41o67M41X48l30P41Y65X77M41Z6bY41Y48P73Y41Z49Z77Y41M6aX41M43o4dX41P49X77Y41M6aP41Z43M4d<41l49o77Z41X6aP41Y43o4dM41<49l77l42Z39Y41X43l41<41l49P41<41X39Y41Y43X41Y41Y49M41Z41X69X41P43Z49P41X4c<67X41X6fY41M43M49X41Y4aZ41P41P6fP41M43<41<41P49o41o42Y41M41P48X73Z41Z66X51o41<67<41l43<41P41<4b<51M41P67Z41l43X41X41o49M67l42Y62o41Z43Y41<41Y49o41P41Y69X41Y43X51<41l65l77P41o6ao41l43l4d<41o49l77Z41X6aM41X43X4dP41l49o77M41Y6a<41Z48o30o41M49<67o41Y72o41Z43X41l41P49l41l41l69<41o43l51l41Y65l77Z41X6aZ41Z43<4dP41o49Z77<41Z6aP41Z43o4dP41Y49P77l41Y6aP41<43M4d<41o49o77<42o39P41Z43l49P41Z49l41Y41Y67P41l46Y30M41Z49Z41Z41<67P41P43l73Z41X49P67l41X6bP41<43o67l41M51<41M42o37<41X48X30<41o49Y41M41l67o41P43Y6bZ41<49M67Z42<62Z41P43Z41Y41l49l41M41Z69P41o43X51X41X65Z77l41M6aP41<43l4dZ41l49X77P41o6a<41Z43Z4dP41X49P77Y41X6al41M48Z30Z41X49M67o41l72Y41Y43Y49X41X4aX41X42X37l41X43Y4dZ41Z49l77Y41P6ao41Z43<4dM41Y49<77l41l6aZ41X43o4dX41o49P77Y42Z39Z41<43o49l41X49<41Z41o67Z41P46l30P41l49P41Z41<67<41Z43M73P41Z49l41P41X67X41P43<49l41P4a<41P41Y6fM41Y43o41o41X49<41M42X41l41o48P73<41Z49Y41<41Z67M41o48Y30Z41o4bP51P41P69M41P46l73l41P4aY41M42<37Z41<43l4dP41Z49<77o41l6aZ41P43o4dP41o66Z51M41l67Y41l43o41<41P58o51M41X72l41P43<49l41l4aY41M41l6fM41X43X41M41o49l41M42Y41M41o48P73P41o66X51Z41M67X41Y43o41X41l4b<51Z41P69M41l46M73<41Y4aZ41Y42M37l41l43X4dl41Y49o77P41P6aY41l43Y4dZ41M49o77Y41Z6aM41o43Z4dY41P49Y77P41X6aP41l48o30P41l58Z51o41X72P41Y43M49Y41o4a<41P41Z2f<41<43l49Z41<57P77M41X6bX41X48<73o41<49X77Y41l6aP41o43<4dX41l49M77o41o6aM41l43M4dP41l49P77Z42l39X41P43Z41Y41l49<41<42Y64M41<43l73o41o49o67P41l6bP41X43<67l41Z51P41P42Y37Y41X43M41P41l49X41Y42P39X41l43X6bY41l49X67P42Y62Y41M43l41X41l49Z41Z41<6bl41l48Z73Y41M49<77o41Z6a<41<43Y4dl41Z66Z51l41X67X41Y43o41X41o58P51Y41l70X41l48<30X41P65l77X41Y67l41l43<41l41M4a<41o42X37Y41Z43o4dl41P49P77Z41P6ao41Z43M4d<41Z49Z77Z41Y6aP41X43M4do41X49Y77P41X6aY41<43<4dM41<66M51P41l67Z41Z43Y41<41<50P51o41l67P41Y43X41P41Y49M67<41X6bM41<43P67<41l49M41X41P67Z41X45M41o41l65M77M41Y67M41X43X41Y41Y66l51<41M70M41l43l41l41Y49l41X41Z69Y41X46Y73X41l49l41Y41Z67P41l43P49<41o4al41o42Z37X41o43M4dM41P49l77l41Z6al41X43Y4dY41M49Z77Y41l6ao41<43o4dM41<66l51<41P69M41M43M73P41X49o41Y41M67M41X43<49M41Y4aP41X42X37P41Z43Z4do41<49Z77o41M6al41l43X4dY41X49Z77o41Y6aX41l43o4dY41o49M77M41M6aM41M48l30M41<49P67X41P67Y41l43Z41<41Z58Y51P41o67Z41o43<41X41o4bo77l41P69M41Y43<51Z41Z4bl41M41P67M41Z43P41l41l51X41Y42P37Z41o48Y30P41l4b<51<41P67o41Y43o41M41Z49l67X42M62X41Y43Y41Z41<49o41M41X6bM41Y48o73Y41P49l77o41X6ao41M43Y4dY41X49M77o41M6a<41P43M4dM41Y49M77X41<6al41Z43M4dZ41<66X51<42P64X41l43P73M41<49M67<41Y6bZ41X48M73X41M49l77<41o6aX41l43l4do41l49<77l41Z6aP41Y43Z4d<41Y49l77o41Z6al41o43o4dY41Z49Y77P42o39o41M43M49P41Y57X77<41P69l41M43M51P41l65o77<41<6aM41Z43P4d<41Z49<77Y41Z6aM41P43M4dZ41o66M51P41Y69Z41<43Y73<41P49P67P41Y6bX41P48X73Z41Y49<77o41Y6al41P43Y4do41Y49Z77o41Y6al41Y43X4dl41Y49<77X41o6aY41Z43P4dM41Y49Y77Z41M6al41Y48o30M41X49Z67P42l64o41Z43<41M41M49P41l42<39Z41X43Y41P41Y49Z41Z41X70M41Y44P73X41M49Y41Z41<67Z41P43M59l41P4ao41X42l37X41l43P4do41Z49Z77X41M6aY41o43Y4dZ41<49P77X41o6aZ41l43M4dX41P49Y77o41Z6aY41<43P4dM41M66X51<41l6fM41P43<49o41o49l41o41Y67l41X43l51<41X65<77Y41Y6aP41P43P4do41Z49Z77Z41X6a<41M43P4dY41<49Y77<41P6aZ41X43Z4dP41M49Z77l41l6ao41P48l30X41o49<41P41X67Y41o43o67X41<49<41Y41Y67X41o43o51<41Y65M77Y41Y6aZ41Y48o30l41<4ao41M42l37Y41Z43o4dl41X49P77Y41Y6aX41<43<4do41X49<77Y41P6a<41M43M4dM41P49X77l41o6a<41Y48l30Y41<4aZ41M42o37l41Z43Y4dY41Z49Z77<41X6a<41l43Y4dZ41M66o51Z41l72Z41Y43Y51<41l65l77M41P6aY41l48o30<41P4aM41Y42o37<41l43l4dZ41P49l77Z41<6aY41P43l4dZ41l49o77Y41<6al41P43o4dZ41X49X77<41l6aY41M43M4d<41l49Y77l42M39l41P43Z51Z41X65M77<41<6aZ41Y43l4d<41M49l77o41P6aP41l43X4dl41X49P77Y42M39o41M43X41l41Z49M41<41l72Y41o43X41X41Z49<41X41Z6bM41Y48Z73Z41Z49Y77P42Z39Y41l43P51Y41o65M77o41Y6aM41P43P4dZ41P49o77M41M6aY41M43Y4dZ41M49P77o41X6aZ41X48Z30<41X4a<41M42P37l41X43Z4do41Y49Z77P41P6aX41Y43P4do41M66Y51X41o6b<41o48X73P41Y49X77X41M6aP41Y43Y4dZ41X49Z77Z41X6aM41Z43M4dM41X49Y77<42Y39l41<43o41Z41Y49Y41Z41X72X41l43<41X41P49X41Z41<6bZ41Z48l73l41l49Y77o42M39Y41o43l51<41Y65M77<41Z6aY41P43Y4d<41o49Z77M41l6aX41Y43Y4dX41M49Y77Y41Z6al41M48X30<41l4aP41Y42P37Z41Y43Z4dY41Y49Z77l41l6ao41Z43o4dl41Z49M77M41X6aZ41P43P4dM41P66o51P41Y6bY41o48Y73<41M49o77<41<6aP41Y48Y30Z41<49o41l41X67o41Z43l73l41Z4aZ41Z42l37Z41Z43P4dl41<66<51<41<6b<41<48<73l41l49o77M41Z6aZ41Z43o4dX41l49P77o41M6ao41Z43Y4dY41l49X77M41X6aY41l43P4dl41X66M51<41X6bM41o48<73P41Y49Y77o41l6aZ41o43o4dM41M49P77M41Y6aM41M43l4dZ41Z49Z77<41<6aZ41X43l4dZ41P49Z77<41<6ao41<43l4dP41o66P51P41Y72o41Y43P41l41Y49P41P41X6bo41M48<73l41P49M77Z42l39Z41P43M51M41P65P77P41Z6aY41Z43Y4dY41X49o77Z41X6aZ41P43M4d<41Z49o77X41X6ao41Y43Y4dX41M49P77<41Z6ao41P43o4dY41X66Z51X41X6bP41Y48<73X41X49Z77Z41Z6aP41o48o30P41M49M41P41<67M41o43Y73l41l49P41Z41o67l41X43o51Y41<65X77Y41X6ao41<48<30Y41<4aP41P42l37Y41P43l4dX41<49M77Z42M39Z41<43Z51P41<65Y77o41o6aP41P43Z4dZ41l49X77o41X6aZ41<43P4dM41<49P77Y42M39o41Z43X41M41Y49o41Z41l72Y41l43o41o41X49M41Z41Z6bo41M48P73Y41<49Z77Z42o39Y41P43P51o41X65Z77o41Y6aP41M43Z4dY41Z49X77o41M6aY41<43X4dM41o49Z77l41l6a<41M48o30o41o4aX41Z42M37M41<43<4do41M49o77M41l6aP41<43Z4dZ41o66M51Z41Y6bP41l48Z73o41P49<77<41l6aM41Z43l4d<41P49<77o41Y6aX41M43<4dP41o49<77<41X6al41o48Y30o41Z4bZ77Z41P6b<41X48M73X41o49X77M42Y39l41o43P51<41l65Y77Z41o6al41X43o4dP41l49Z77Y41o6aX41M43X4dX41l49<77P41o6aX41Z48X30o41X4a<41Y42X37<41M43Z4d<41o49X77X41l6aY41X43<4dY41Y66P51M41<6bl41M48o73Y41Y49<77l41X6aP41X43Z4dY41Y49l77Z41o6ao41M43o4dM41M49l77M42Z39l41<43l41o41l49<41o41M72Y41M43o51M41l65M77X41P6a<41P48P30Y41X4aY41Z42Z37Y41Y43<4dY41X49Y77Y42<39Z41<43X51Z41Y65P77M41o6aZ41o43l4dP41l66l51l41Y67P41o43P41Y41X4bP77l41Y6bl41M48M73M41M49X77X42Y39<41<43X51Z41l65Z77X41Z6ao41X43l4dZ41Z49P77X41l6a<41M43l4d<41Y49<77P41Z6aX41Z48X30P41M4a<41X42M37M41o43o4dZ41o49Y77Z41o6aX41Y43o4dl41<49P77M41l6aY41<43P4dZ41<66Y51o41P6bP41P48P73<41Y49P77<41P6aY41M43l4dX41<49<77X41M6al41o43Y4dl41X49M77P41Z6aP41l48Z30Y41M4b<77Y41M6bP41o48Y73P41Y49P77Z42X39o41Z43Z51o41P65o77Y41o6a<41l43P4dX41M49<77X42l39<41l43X51Y41Y65Y77Z41<6ao41o43<4dM41l49P77<41l6al41M43l4dP41o66o51o41l72o41l43M51X41P65o77M41l6ao41Z48l30o41M4aY41P42Z37Y41l43Y4dP41M49P77l41<6al41Z43Z4dM41l49M77X41Y6ao41P43o4dX41l49<77<41o6aY41X48M30l41M4al41M42P37Z41Y43M4d<41<49M77X41<6aP41M43P4dZ41X49o77X41o6aM41P43o4dP41l49Z77M41Z6a<41<43M4dP41Y49M77P41M6aX41X48Z30P41X49<41P41X67l41P43<73Y41X49M41X41Y67l41l43M51X41M65l77M41P6aY41o48o30<41Y4ao41P42o37M41<43M4dl41<49o77o41<6aZ41P43o4do41X49l77X41o6aX41Z43l4dY41o49l77<42P39P41X43<51o41M65Y77P41o6aM41M43<4dY41<49M77X41Y6aP41Y43M4d<41Z49Z77X41Z6aX41o43P4dP41Z49Z77Z41M6aX41l43X4dP41Z66M51<41Z72Y41M43M51l41l65Y77X41<6aP41M48X30P41Z4al41P42o37Y41o43l4dP41Y49P77P41Y6aP41X43l4dX41o49P77Y41<6ao41Z43o4dZ41Z66Z51o41<6bo41<48M73P41<49o77X41<6aM41X43X4dZ41M49Y77M41<6aZ41l43Z4dY41Y49o77o42X39Z41o43P51X41Z65Y77Z41<6aZ41l43P4dX41M49Y77M41Y6aM41<43o4dM41X49<77P41P6aZ41<48l30X41X49Z41l41<67Y41Z43P73Z41l49X41P41X67X41Z43M51l41<65<77Z41P6aY41l48Y30l41Z4aX41Y42P37Z41P43l4d<41X49X77Y41Y6aZ41Z43X4dX41X49Y77X41X6aY41X43Y4do41X66M51Y41M6bZ41Y48l73l41P49P77o41<6aY41Z43<4dZ41X49P77o42<39M41P43Y51Z41Y65l77X41P6aY41P43P4dM41P66<51Y41P67Z41Y43Z41Z41M4bM77l41o67P41Z43P41X41<4aY41Y42Z37o41M43o4dM41Z66l51l41M6bZ41<48X73l41X49<77<41Z6aX41<43o4dP41Y49Z77l41Y6ao41l43X4dY41M49l77<41<6aX41P43o4do41Z49P77l41l6aM41Y48l30Z41Y4al41Z42<37<41Y43o4dP41Z49M77<42Y39l41Z43M73l41l4aX41<42M37M41M43Z4do41Z66P51X41X6bX41X48P73Z41Z49X77Y41X6al41l48P30P41<4aZ41X42P37X41o43P4do41M49P77Y41l6al41Y43l4dl41Y49Z77M41Z6aZ41l48X30l41M4bX77X41Y67M41Y43Z41o41Y4a<41l42Z37M41Y43M4dl41l66<51X41X6bP41P48P73Y41Y49l77Y41Y6a<41<43o4dM41Y49X77M41X6al41X43Z4dM41X49o77M42M39X41Z43l51<41<65<77o41M6aY41<43X4dP41l49<77X41<6aP41P48X30Y41o4ao41M42o37Y41<43Z4d<41Y49M77Y41Y6aP41X43P4dl41Y49o77P41l6aX41Z43P4dM41o49l77Z42l39l41P43o73Z41<4aM41<42o37X41o43l4dY41Z66<51P41o6bM41M48M73<41Y49o77M41l6a<41M43l4dX41Y49l77o41Y6ao41l43o4dl41M49Z77P42Y39M41M43M51P41l65o77o41l6aM41l43P4dZ41l49P77Y41l6aP41P48l30X41M4aM41<42<37P41X43<4d<41Z49P77o41l6a<41<43<4dM41M49o77<41l6al41M43Z4d<41l66M51<41Z72Y41l43X41M41Y49M41X41Y6bP41<48<73P41M49o77M42Z39l41X43P51<41<65<77Y41<6aP41l43Z4dP41<66X51Y41l6bl41Z48X73M41l49o77M41o6aX41Y48o30o41P4bX77M41o6bY41o48Z73<41P49l77Y42Y39M41M43l51Y41l65X77o41<6aY41M43Z4dX41Y49Z77Y41M6a<41P43o4do41<49Z77M41<6aX41<48X30M41l4ao41<42o37l41M43X4dY41<49<77M41<6aM41l43<4dl41P49X77Y41P6aM41<43X4do41M66Z51<41P6bP41<48Y73o41l49o77Z41M6aM41l43o4dl41l49l77Z41Y6aP41o43l4do41l49X77M41X6aM41Y48M30<41l49<41Y41<67Z41P43Z73Y41M49Y41P41Z67o41Z43M51Y41M65P77<41Y6aP41Z48<30o41l4al41l42Z37M41X43o4dl41X49o77Y41Y6al41M48o30<41M4aY41M42Z37l41l43<4dM41Z49o77o41Z6aY41X43o4dM41Y49P77o42Z39l41M43P73o41X49l41Y41M67M41P43Z51o41X65Y77Y41<6aM41Z48<30Y41P4aX41o42P37P41o43<4do41<49<77o41<6aY41<43o4dP41<49P77P41Z6aM41P48Y30o41Z4aX41M42P37M41<43P4dl41P49o77<41o6a<41Z43P4dX41<49Y77P41o6a<41o43P4dX41Y49<77l41Z6ao41X43<4do41o49l77<42<39Y41l43Z73<41X49P41<41<67Z41M43Z51l41l65P77l41M6a<41Y48Z30Z41o4al41P42P37<41P43<4do41o49Z77l41l6aZ41l43o4dl41l49Y77<41Z6aX41M48M30o41Y4al41Z42P37o41<43o4dY41l49Y77X41Y6aY41X48X30P41P4b<77Y41Z6bP41<48Z73X41X49X77X42<39Y41P43<51<41Z65<77<41<6al41P43<4dY41Z66o51<41Y6bY41o48X73Y41l49M77o41M6aM41P48Y30<41X4bM77l41l67P41<43<41<41Y4a<41Z42<37M41o43o4do41Z66<51l41Y6bl41Z48P73Z41Y49<77P41l6al41l43<4dY41M49o77<41X6al41P43P4d<41<49l77Y42X39Z41Y43M51Z41l65X77l41Y6al41l43X4dP41Z49<77X41P6aM41Z43l4dY41M49P77M41Y6aY41P48P30P41o4a<41P42o37o41<43M4dY41Z49l77o41X6al41Z43Y4dl41X49M77Y41M6aY41P43Z4dY41Z49o77X41Z6al41P48M30l41P4bY77Z41Z67l41P43l41X41Z4aM41l42l37Z41P43M4dZ41<66P51M41Y6bX41M48<73M41P49X77Y41o6aP41<43P4do41Z49l77Y41X6aZ41X43P4dP41M49P77Y42X39o41X43M51o41o65o77Y41X6aZ41l43l4dX41P49Y77X41o6aZ41M48X30M41l4aP41M42X37o41l43M4dM41Y49o77P41M6al41M43l4dl41<49Z77M41<6aZ41X43M4do41Y49X77<41Y6aZ41l43Y4dX41M49Z77M41o6ao41Z48M30l41Z49X41o41Z67P41P43P73M41l4aY41M42X37P41P43l4dX41M66X51M41l6b<41l48o73M41M49X77M41Y6aX41M43X4dX41l49<77Y41o6al41M43Y4dM41l49X77Y42o39M41l43Y51<41o65P77M41Y6aM41l43P4dZ41o49X77o41M6aY41o43o4d<41o49X77Y41M6a<41Z48Y30Y41l4ao41l42l37o41<43<4dZ41M49<77<41Y6a<41X43o4dP41<49Z77M42o39l41M43X73M41Y49X41o41M67o41l43P51o41X65o77M41X6aZ41X48o30o41<4aX41l42l37o41X43o4dY41Z49Y77l41o6aZ41<43X4dY41M49M77<41<6ao41o43P4d<41l66P51Z41o6bo41o48Y73Z41M49X77P41Y6a<41<43Z4dX41X49M77Z41Z6a<41Z43M4do41Z49o77o42<39o41l43o51l41P65X77Y41<6a<41l43o4dl41<49X77P41X6a<41<43X4dM41Y49<77o41M6aZ41o43o4dl41Z66Y51l41M72X41M43<51X41M65Y77P41X6a<41o48P30<41P4aY41Z42l37X41Y43<4dl41Y49o77Z41M6aX41o43l4dM41M49l77o41Y6aX41o43Y4d<41Y49<77M41o6aM41Z48M30<41Y4ao41o42X37Y41X43M4dP41P49X77X41M6aX41Y43l4do41P49M77M41o6aZ41P43<4dX41<49Y77M42M39Z41<43Y41l41<49Y41Y41Z72Z41Z43<51o41o65o77X41X6aM41Y48o30X41X4al41M42Y37X41<43X4d<41Z49Y77P41o6aM41l43o4dY41o49Z77Z41M6aZ41o48Y30o41l4ao41P42<37M41X43P4dY41l49l77P41M6aZ41o48X30Y41Y4bP77M41<6bM41Z48X73l41o49l77P42P39P41P43o51l41Z65P77M41l6a<41l43X4dZ41X49l77<41Y6ao41l43l4dM41Y49o77Y41P6aZ41<48l30Y41P4al41X42l37P41l43P4dl41<49Y77l41M6al41X43M4dY41l66o51Z41o6b<41Z48l73<41M49o77M41P6a<41Y43l4dZ41l49<77o41M6aX41P43l4dX41P49Z77P41M6aP41X43M4dl41X66X51P41P72l41<43Z51o41Z65Y77<41Y6aZ41P48X30Z41X4aP41Z42X37l41X43Y4dM41M49o77Y41l6al41l43o4dX41M49Z77<41<6aY41o43X4dl41Z66<51l41Z6bX41<48l73o41Z49X77l41M6aM41X43M4do41l49X77Z42M39M41<43X51<41X65o77P41Y6a<41M43P4dZ41P49Z77Z41P6aX41Z43X4do41Y49M77P41o6ao41X48M30l41P4bY77l41Z6bZ41<48l73<41l49Z77P42o39o41M43P51M41X65o77Y41Z6al41Y43X4dP41Z49M77l41Z6aM41<43M4dM41l49X77l41l6aY41Y48l30Z41M4aY41Z42o37<41<43<4dY41P49Z77<41Y6aP41o43Z4dl41M66P51o41M6bX41<48Z73o41o49l77M41Y6al41Y43l4d<41o49X77Z41Z6a<41M43Z4dY41Y66l51l41X67Y41X43o41Z41P4bl77l41<67P41M43Z41<41o4aZ41X42l37X41Y43o4dZ41Z66Z51X41X6bM41l48o73o41l49Y77M41o6aM41X43Y4dX41M49Y77P41<6aM41M43Y4dZ41X49Z77M42P39o41<43<51<41M65Y77l41Y6aZ41X43X4dM41o49X77Z41o6aY41l48M30M41l4a<41P42M37P41o43P4dZ41P49o77X41Y6aP41o43l4do41o49Y77Z41Z6aZ41Y48M30l41l4bM77Y41P67Y41<43l41P41l4aM41Z42l37Z41P43Y4d<41Y66l51Z41X6bM41X48Y73X41l49X77o41X6aZ41o43P4dZ41Z49l77X41<6ao41P43M4d<41M49Z77M41X6a<41<43Z4dZ41M66<51l41X6bo41Z48Z73o41X49<77Z41P6a<41Z43<4do41M49l77l41l6al41M43P4dP41l49l77P42P39o41l43X73<41o49X41o41Z67P41l43l51<41<65<77l41P6al41M48X30X41<4aY41M42o37<41<43l4do41X49M77X41P6aM41P43o4dP41X49P77P41P6aX41M43M4dZ41l49l77Y41X6ao41Z48Y30M41X4al41P42o37Y41M43<4do41P49X77P41<6aX41<43P4dl41P49M77o41M6al41l43l4dZ41l49l77<42o39l41l43Y73X41Y49P41Z41o67<41Z43l51P41l65Y77P41P6a<41o48X30Y41l4aZ41X42P37l41<43P4dM41M49Y77M41Z6aY41X43<4dY41l49Y77M41<6aY41l48M30Y41X4aX41M42Z37Y41P43Y4dl41M49Y77l41<6aX41<43o4dZ41X66P51P41M67<41X43l41P41M4bo77<41Y6bM41<48X73P41Z49X77<42M39Y41X43P51Z41P65Y77X41Y6al41P43X4dl41M49X77o41Z6aZ41P43o4dl41l49X77o41Z6ao41<48M30Z41Y4aY41Y42l37P41<43<4dX41P49M77Z41M6ao41o43P4dl41P49P77l41M6al41X43Y4dM41<66P51X41X6bo41o48Z73X41P49M77Y41l6aP41Z43Z4dP41l49P77M41P6aZ41o43M4dM41P49o77l42P39P41X43M41X41Y49<41Y41Y72Y41l43<51P41X65l77Z41Z6aX41X48<30Y41X4a<41l42l37<41Y43o4d<41Z49Z77l41<6aY41P43M4d<41M49Z77P41o6aP41Z43P4dM41l66o51Z41Y6bZ41M48l73o41l49X77P41Y6aZ41<43o4do41o49<77M41Y6a<41Z43Y4dX41l49l77l42Z39<41o43Z51Y41Y65X77Z41X6a<41l43Y4dM41<49Z77M41P6aY41o43Y4dl41Y66P51o41X67l41Y43Y41<41M4bX77Y41P67M41P43o41M41Y4aP41o42Z37Z41o43M4dM41l66P51P41<6bY41X48P73P41X49<77M41Z6a<41Z43l4do41X49Y77P41X6aZ41o43Y4dX41<49Z77o42Y39P41Z43P51M41<65l77Y41o6ao41o43X4dM41<49<77P41Y6al41<43Z4dl41X49Y77Z41o6aY41<48Y30X41l4aX41Y42M37o41M43P4dZ41l49Z77o41Z6al41<43o4dY41<49<77P41o6aP41P43P4dP41l49M77<41l6ao41Y43X4dY41X49<77Z42X39o41X43Y73l41o4aX41P42l37<41P43P4dY41o66o51X41Y6bY41l48<73Z41P49Z77M41M6aP41Z43o4dP41P49Z77Y41M6aM41Y43Z4do41P49<77<42l39Y41X43l51o41o65l77l41l6aX41M43P4dM41Y49Z77Z41Z6aM41l43Z4d<41l49P77Z41P6aX41X48Z30X41Y4aX41X42l37P41Z43X4d<41Z49<77P41l6aM41Y43<4d<41l49l77o42P39P41X43l73P41l4aX41X42<37X41l43Z4dP41o66X51M41l6b<41l48X73Z41P49l77Y41Z6a<41Y43o4do41<49<77Y41o6aY41o43l4dP41P49M77P41l6ao41Y43<4dZ41Y66Y51<41P6bX41<48M73P41o49Z77P41X6aM41P43<4dM41Z49Z77X42P39M41o43Y73<41<49M41X41X67Z41Y43l51M41Z65P77X41Z6a<41Y48l30M41P4aM41o42X37X41l43X4dP41Y49P77Y41<6aP41l48Z30M41o4aP41Y42<37P41l43Z4dM41P49Z77Y41X6aP41Y43Y4dY41l49P77Z41X6a<41l43o4dM41<49Y77X41Z6aM41Y48X30Z41Z4bP77<41<67Y41o43o41M41l4al41o42o37X41P43M4dM41Y66Z51l41<6b<41o48P73M41Z49Y77l41Y6aY41<43X4dZ41l49o77Y41o6aY41X43Y4do41l49l77P41o6ao41M43<4dl41Y49M77l41l6aP41M48X30<41M4al41X42X37Z41X43M4dM41Z49Y77Y41Z6a<41<43Z4dX41Y49Y77P42M39P41l43X73o41Y49l41M41X67P41Z43<51o41Y65<77M41Y6aZ41X48P30Z41o4a<41X42l37Y41l43M4dX41M49P77P41M6ao41Z43X4dX41M49l77P41Y6ao41Z43Y4dP41<66<51o41P6bM41l48Y73P41X49Z77P41Y6al41Z43o4do41X49<77X42Z39Z41Y43o51Z41l65l77X41<6aM41Y43P4d<41l49P77<41Z6aZ41<43o4dZ41o49l77Y41P6a<41M43P4dM41X49Z77Y41Z6aM41M43P4d<41Z49X77X42<39o41Y43l41Y41Z49<41<41Y72<41<43P41M41Y49l41Y41Z6bl41X48<73l41X49X77X42M39o41<43Y51<41Z65l77l41l6aM41Y43P4dZ41o49P77Y42M39X41o43X51Y41l65M77Y41Z6al41M43<4dX41o49l77X41o6aY41o43o4dX41P66o51Z41o67P41l43o41M41Z4bY77P41M6bM41o48Y73Z41Z49X77Z42M39<41o43Y51Z41l65Y77P41Z6ao41M43Y4dX41<49Z77Y41X6aP41M43<4dY41Y49Y77<41P6aZ41Z43o4d<41l49M77l41o6aP41M43X4d<41M49M77o42X39l41Z43<51M41l65P77M41X6aM41X43X4dl41o49<77l41Z6al41<43<4do41P49o77M42<39o41<43M73P41X4aM41l42M37X41Y43P4d<41Z66o51Z41Y6bP41M48o73P41o49<77o41Y6aZ41l43X4d<41M49o77Z41P6a<41P43M4dZ41o49M77<41P6aZ41<43l4dP41o66X51X41Y6bY41o48Z73Z41P49Z77M41Y6aP41Y43<4d<41P49M77P41M6aM41M43<4dl41M49P77Z42Y39X41Z43Z73X41M4aY41o42Z37P41Z43l4d<41<66M51l41o6bP41<48Y73Y41M49Y77Z41X6al41Z43Z4dl41o66o51M41<6bY41Z48P73l41Z49l77Z41P6a<41l43M4dM41l49X77l41l6aX41<43o4dY41Y49Z77Y41Z6aZ41l43M4do41Y66<51Z41X67X41X43M41Y41l4bo77X41X6bP41M48P73<41P49<77M42Z39X41Z43o51M41Z65<77Y41Y6al41<43Z4do41Z49Z77P41l6aY41Y43<4dl41Y49o77X41Y6ao41P43l4d<41Z49P77o42M39o41X43Z51X41M65X77<41o6aX41Y43X4dX41X49P77<41Y6aY41Z43<4d<41<49M77Y41<6a<41M43l4dM41M49Y77X42l39Y41M43<73P41P49<41o41Z67Z41Y43Z51Z41M65<77Y41X6aP41<48o30Z41l4aP41l42M37o41l43M4d<41M49o77P41X6aY41l48X30X41X4aY41Z42Z37Z41<43l4d<41Y49X77Z41<6aZ41X43P4dM41Y49M77l42Y39M41o43l41o41o49M41<41l72X41Z43o41X41X49<41l41Y6bX41X48X73X41Z49Y77Z42Z39<41o43o51P41P65l77Y41M6al41X43l4dZ41Y49o77o41X6ao41Y43M4d<41Y49P77P41<6aZ41<43<4dM41X49M77<42X39o41<43<51Y41X65X77<41Y6al41P43<4dP41Z66<51X41M67o41P43M41M41M4bP77o41<6b<41P48Y73M41Z49Z77Z42X39Y41X43Z51Z41M65Y77o41X6aY41o43<4do41X49M77X41o6al41l43Z4dl41X49M77Y41<6a<41M43o4do41P49o77Z42l39M41l43M51X41l65<77o41P6aY41l43X4dZ41l49M77o41l6ao41Y43<4do41X49Z77<42M39o41X43X73M41M49P41M41o67Z41P43l51X41X65<77Z41X6aP41Y48X30o41P4aY41M42M37<41X43M4d<41o49l77l41M6aX41l43P4dM41M49l77Y41Y6aY41Y43M4dZ41P49X77P41M6aM41l48l30o41P4aY41l42Z37<41X43<4dl41P49P77<41M6a<41l43Z4dl41Z49M77<41<6aZ41l43X4dZ41l49M77Y41X6aY41P48P30X41Y49<41Y41Z67P41Y43Z73o41l49l41X41<67o41X43<51Y41l65<77M41Y6al41l48Z30P41o4al41<42Y37Y41X43<4dY41M49P77o41Z6aX41<48Z30Z41l4aM41o42o37P41P43l4dP41M49X77X41<6aZ41P43Y4dP41X49o77M42l39P41l43X73X41M4aY41P42Z37M41Z43X4dX41l66l51P41l6bY41l48Y73X41P49<77M41P6aM41<43o4dM41o66o51X41P6bo41Z48Z73M41l49Y77l41l6a<41P43Z4d<41M49l77l41<6aY41Z43l4dM41Y49l77Y41o6aY41X43o4do41P66l51o41o67P41l43M41P41M4bP77o41Z67M41X43<41M41Z4aX41X42o37o41P43o4dZ41l66P51M41X6bY41M48Y73X41l49o77X41Z6al41Z43l4dP41M49o77<41P6aP41P43Y4dM41Z49<77M41P6aX41M43<4dX41M49<77o41l6a<41X48Z30Y41M4aX41l42Y37X41<43Z4dX41X49Y77X41<6aP41Y43P4dY41Z49o77Y42M39Z41l43Z41Z41Y49Z41l41l72X41l43X51<41P65X77M41Y6aP41X48<30P41Y4aP41Y42M37l41l43Y4d<41o49P77Z42P39l41Y43o51X41P65<77<41l6ao41<43<4dZ41o49<77Y41M6aX41Y43l4dP41X49o77Y41o6aP41M43o4dZ41<49Y77M41l6aM41X43l4dY41l66l51o41X72<41o43X51o41Y65o77Z41Z6aY41P48M30M41Y4aX41Y42M37X41<43X4dl41o49o77l42o39<41<43l51o41Z65M77Z41Y6aP41l43P4do41o66o51o41X67Z41P43l41P41X4bl77P41Y67l41o43P41<41o4aZ41P42P37M41Y43<4d<41P66M51X41M6bY41Y48P73o41M49l77l41o6aZ41M43P4dP41P49<77P41<6aY41<43Z4do41Y49Y77Y42Y39X41P43o51Y41Z65P77l41o6ao41P43Y4dM41<49Y77Y41o6a<41M48P30o41Z4aM41<42o37P41X43l4dY41<49<77l41P6aP41M43o4dZ41Z49M77<41X6ao41X43Y4dM41Y49P77M41M6aP41Z43Y4dP41o49o77<42X39o41P43l41X41l49M41X41P72o41X43Y51l41M65X77Y41Y6al41l48l30l41X4aP41X42o37<41M43M4dZ41P49l77M41X6al41P43M4do41X49P77P41M6a<41<43l4dl41o66o51o41o6bo41Z48Z73<41<49l77P41M6aP41Y43Y4dZ41l49Z77M42<39P41P43X51l41M65P77l41M6aZ41<43l4dl41P49X77Z41Y6a<41M43o4dX41o49Y77Y41P6ao41l48Y30l41M49M41l41<67P41M43M73l41o4aZ41X42P37<41<43M4dX41Y66P51Z41X6bX41Z48X73l41P49M77l41M6a<41l43P4dX41l49X77M41l6aZ41X43Z4dY41P49o77M42l39l41<43Z51X41l65X77<41Z6aM41<43Z4dX41Y49P77Y41M6ao41l48Y30<41P4a<41P42<37P41M43M4dP41X49X77<41M6ao41P43Y4dY41<66P51Y41o72Z41P43<41<41P49X41Z41o6b<41<48Z73M41o49X77l42M39l41o43X51M41Y65M77M41Z6aM41Y43X4dY41X49M77M42o39l41<43P51<41Z65P77o41<6aX41l43P4dM41<49Y77<42o39<41Z43l73<41P4a<41o42M37X41l43<4dl41P66M51Z41P6bM41l48o73X41X49Z77P41l6aZ41<43M4dM41o66X51X41l6bX41o48o73Z41<49l77Z41<6ao41P43<4dM41Y49<77<41l6aM41l43M4dM41Y49M77o41o6aY41Y43X4dP41l66P51Y41P67M41M43M41X41P4b<77M41Y6bo41<48Z73X41Y49Z77X42Y39P41M43<51P41o65Z77M41P6aP41<43M4dP41P49Y77M41M6a<41M43<4dZ41<49<77M41l6al41l43P4dY41l49Z77M42<39X41Z43l51P41M65P77o41Z6aY41Z43<4dX41o49X77X41l6aY41M43P4d<41M49<77M41Z6aP41M43Y4dl41<49M77M42<39<41l43l73Y41o49P41P41Z67P41Y43Y51l41M65Y77X41Z6aX41X48o30Z41M4aX41X42l37Y41<43X4dZ41o49<77Z41<6ao41<48Y30Z41l4aZ41o42X37o41M43o4dX41Y49Y77Z41o6aY41M43X4dZ41M49l77P42X39X41<43Z73Z41o4ao41P42X37Z41P43M4dX41Y66X51X41l6bX41M48P73Y41P49P77Z41Y6aY41l43Z4dP41<49X77X41<6aX41o43<4d<41M49P77o41Y6aZ41Y43l4dP41M49Y77Y41<6aZ41<43P4dP41Y66l51M41M6bP41Y48M73M41o49l77X41<6aM41Z43X4dZ41o49<77Z41Z6aP41o43Y4do41Z49o77o42M39X41X43Z73Z41Z4aP41M42Y37Z41P43l4dP41X66l51P41<6b<41Y48P73<41Y49l77Y41Y6a<41l43o4dZ41P49<77M41l6al41X43X4dZ41P49Z77o41l6ao41X43o4do41o66M51X41Z6bo41l48P73X41o49<77P41<6aY41X43Y4dX41X49l77P41l6al41X43l4dP41<49<77Y42M39<41M43o41o41X49X41Z41X72Z41X43l51Z41X65Z77o41Z6al41o48l30Y41P4al41P42M37o41o43o4d<41l49l77X41Y6aM41M48X30<41l4aP41Y42P37P41P43o4dX41P49l77<41Z6aP41o43P4dM41P49<77X42X39Z41M43Y41P41Y49o41o41X72M41o43X41P41Y49Z41l41<6bX41l48X73X41P49P77M42o39P41o43Y51<41l65P77<41Y6ao41o43o4dP41M49l77P41X6ao41l43Y4dl41<49<77l41l6al41o48M30M41<4aP41X42X37P41Z43<4d<41P49P77Y41Z6al41l43<4dl41X49M77o42X39Y41l43o51Z41P65P77<41Z6aP41P43l4dM41M49Y77Z41Y6aY41X43P4dX41l49<77Y41l6a<41Z43P4do41<49P77Z42l39<41Y43X73Z41M4aX41P42o37X41Y43Z4dM41P66<51X41l6bX41M48<73P41M49P77Z41X6aX41o43X4dM41<66l51Y41l6bZ41l48<73<41X49l77P41l6aP41Z43Y4dP41l49X77M41Z6aM41P48l30o41Z4bX77X41<67o41M43M41<41Y4a<41X42o37l41l43X4do41M66Z51M41Y6bo41X48l73M41<49P77l41Z6a<41Y43l4dZ41<49Y77<41Z6aM41l43l4dM41<49l77P41l6aM41Y43X4dP41<49o77M41P6a<41<48l30o41M4aZ41l42Y37P41M43l4dP41<49<77<42<39Z41P43Z41X41Y49l41o41X72P41<43X41<41<49M41<41Y6bM41M48P73X41o49l77<42<39X41P43Y51o41M65l77o41o6aM41Y43X4d<41Y49M77Y41P6aX41P43<4dX41o49M77P41<6aP41<48o30M41Z4al41X42Z37X41Z43P4dX41<49Z77Z41Y6aM41Z43l4d<41Y49P77Y41P6aY41l43<4dP41<66M51<41Z6b<41Z48Z73Z41o49<77P41<6aY41<43<4dM41Y49o77Z41Z6aY41l43<4do41X49o77M41Z6aZ41Z43o4dY41o49Z77Y41<6ao41P48Y30Z41P4bY77l41l6bl41X48Y73<41X49X77P42l39Y41o43<51M41M65l77l41M6aX41X43M4dM41o49o77M41o6aX41o43o4dX41Y49Z77o41o6aM41l48M30Z41l4aM41l42P37Z41l43Y4dX41M49P77P41Z6aY41Z43Z4dP41<49P77Z41o6al41Z43Z4do41P66l51l41o6bo41<48Z73P41M49l77P41X6aP41<43l4d<41l49X77M41P6aX41P43o4dZ41X49o77<41M6ao41Y48M30l41X49<41M41l67M41Z43o73<41M49X41l41P67Z41o43Z51X41P65o77<41X6ao41M48X30P41o4a<41l42X37M41Z43X4dZ41o49P77Y41o6aM41M43X4dP41M49X77Y41Z6aZ41Z43Y4do41Y49X77Y41<6al41Z48P30X41o4al41M42o37Y41l43<4dZ41P49<77l41Z6al41<43P4do41M49X77X41o6aY41M43P4dl41o49X77Z41X6al41l43l4dX41M49l77Y41M6aZ41P48P30o41l49o41<41P67<41<43o73Y41P4a<41o42Y37l41<43l4dY41X66X51Z41Z6bl41P48M73M41M49Z77Z41M6ao41l43o4do41Y49<77P41l6aX41Y43X4dM41<49o77o41X6ao41X43M4dP41M49X77l41<6aY41Z48Z30Z41o4ao41P42o37o41X43X4d<41<49o77Y41X6aM41o43Y4dP41<49M77<41Z6aZ41l48P30Y41<49P41<41Z67M41P43o73M41o49Y41Z41Y67o41Y43o51X41P65Z77Z41P6a<41M48<30M41X4ao41Z42M37Y41l43o4dY41Z49<77X41Z6aX41l43X4dP41l49<77l41P6aM41X43o4do41P66<51X41Y6bX41Z48Y73M41<49X77o41<6al41M43X4d<41Z49X77M41<6aX41X43Z4dl41o49X77P42M39o41o43Z51l41o65P77o41Z6a<41Z43X4dY41Y49Z77<41Y6aZ41M43X4dM41o49o77X41o6ao41<43M4dM41<49P77X41Z6a<41<43P4dX41<66<51M41o72P41l43X51o41Y65l77Z41X6aX41P48P30P41o4aZ41l42M37P41M43l4dZ41l49P77l41X6al41M43<4dM41Y49l77l41P6a<41<43P4dl41Y66<51<41P6b<41Z48P73P41P49M77M41Z6aM41<43P4dM41l49P77Z42X39<41o43M51l41M65Y77X41<6ao41X43o4dM41M49X77Y41Y6aP41X43Z4dP41o49<77o42<39M41<43o41M41Z49M41X41Z72l41o43M41<41P49l41P41P6bo41M48o73<41M49M77<42Z39M41P43l51o41<65P77P41M6aM41Z43Z4do41X49X77Y41Y6aP41o43M4dZ41P49M77Y41Z6aY41M48o30Z41o4aM41Y42o37o41M43X4dX41P49Z77l41M6a<41P43o4dP41M66o51P41Y6bY41Z48Y73o41M49P77X41<6al41o43<4dP41Y49Z77l41M6aM41M43Z4d<41<66<51P41o70M41X43o41Z41M49l41X41l69P41Y43Z41o41<49l41Y41o70l41Y41P3do3d'.SPLiT('<MZXYoPl' )|ForEacH-obJect{ ( [chaR] ( [cONvert]::tOinT16(([stRIng]$_ ) ,16))) })-join'' )

以上のスクリプト自体は特に悪意のあるものではないため、実際に動かしていただいても問題ありませんが、現場でこのようなスクリプトを考えなしに動かしてしまうことは大きな危険性を伴います。まずはスクリプトから、コマンドレットを実行する箇所を探しましょう。難読化解除の対象は以下のような内容です。

& ((GEt-variabLe '*MDR*').Name[3,11,2]-JOIN'') ( ( '70P6fZ77X65Z72o73Z68Z65Z6cX6cM2eP65X78Z65<20X2do65<6eX63Y20Y4bo41l41l6eY41X48l34l41<4aZ77Z42<38X41l43P55X41Z49l41P41Z67P41Y48P73o41M49X41o41Y67X41Z43M51M41P65l77<41X6aP41<43M4do41o49P77X41l6a<41o43l4do41M49<77<41<6aY41<43M4dM41l49X77P41Y6ao41o48o30<41<49X41<41M67X41l44Y30P41o4bY77Y41X6bo41M43Z67o41X49<41M41Y67X41X43Y6bM41l66<51o42M37Y41o43o41M41Z49Y41<41Z6bP41M48o73Y41o49Y77M41P6aP41Y43l4dX41Y49M77l42o39Z41M43<41<41<49Z41Y41P39l41l <# 省略 #> 41P3do3d'.SPLiT('<MZXYoPl' )|ForEacH-obJect{ ( [chaR] ( [cONvert]::tOinT16(([stRIng]$_ ) ,16))) })-join'' )

以上のスクリプトには、少なくとも目に見える形でpowershell.exeやInvoke-Expressionといった文字列は見当たりません。よって先述の通り、アンパサンド記号やドット記号でpowershell.exeやInvoke-Expressionを実行する形式であることが推測できます。スクリプトの冒頭を見ると、アンパサンド記号があることが分かると思います。アンパサンドに続く、最初の括弧の部分をコピーして、powershell.exeに貼り付けてみましょう。

PS C:\> (GEt-variabLe '*MDR*').Name[3,11,2]-JOIN''
iex
PS C:\>

推測通り、Invoke-Expressionのエイリアスである「iex」という文字列が出力されました。よって解析対象のスクリプト&"iex" <スクリプト本体>という書式で動作するスクリプトであることがわかります。それでは&"iex"の部分を取り除いて、powershell.exeで出力してみましょう。

PS C:\> ( ( '70P6fZ77X65Z72o73Z68Z65Z6cX6cM2eP65X78Z65<20X2do65<6eX63Y20Y4bo41l41l6eY41X48l34l41<4aZ77Z42<38X41l43P55X41Z49 <# 省略 #> 41M6aM41M43Z4d<41<66<51P41o70M41X43o41Z41M49l41X41l69P41Y43Z41o41<49l41Y41o70l41Y41P3do3d'.SPLiT('<MZXYoPl' )|ForEacH-obJect{ ( [chaR] ( [cONvert]::tOinT16(([stRIng]$_ ) ,16))) })-join'' ) | Add-Content -Encoding UTF8 -Path decoded.txt
PS C:\> Get-Content -Encoding UTF8 .\decoded.txt
powershell.exe -enc KAAnAH4AJwB8ACUAIAAgAHsAIAAgACQAewAjACMAIwAjACMAIwAjACMAIwAjAH0AIAAgAD0AKwAkACgAIAAgACkAfQB7ACAAIAAkAHsAIwAjACMAIwB9ACAAIAA9A <# 省略 #> CAAIAArACAAIAAkAHsAIwB9ACQAewAjACMAIwAjACMAIwAjAH0AJAB7ACMAIwAjACMAfQAkAHsAIwAjACMAIwAjACMAfQApACAAIAAiACAAIAApAA==
PS C:\>

Base64エンコードされたPowerShellスクリプトを実行するスクリプトが出力されました。この書式は以前の記事で解説した通り、encオプションに続くBase64エンコードされた文字列をデコードすれば実行内容がわかります。実行内容の文字列をBase64デコードして出力しましょう。

PS C:\> $src = ([System.IO.File]::ReadAllText("C:\decoded.txt") -split "\s+")[2]
PS C:\> $bytes = [System.Convert]::FromBase64String($src)
PS C:\> $dec = [System.Text.Encoding]::Unicode.GetString($bytes)
PS C:\> $dec | Add-Content -Encoding UTF8 -Path .\decoded2.txt
PS C:\> Get-Content -Encoding UTF8 -Path .\decoded2.txt
('~'|%  {  ${##########}  =+$(  )}{  ${####}  =${##########}  }{  ${#######}=++${##########}  }{  ${#####}  =  (  ${##########}  =${##########}+ <# 省略 #> #}${###########}+${#}${#######}${####}${######}  +  ${#}${#######}${####}${######})  "  )
PS C:\>

まだ可読性があるスクリプトにはなっていません。難解なスクリプトではありますがやることは変わりません。powershell.exeやInvoke-Expressionが目に見える形では出力されていないため、アンパサンド記号またはドット記号の位置を探しましょう。最初のセミコロン直後にアンパサンド記号があることがわかります。

PS C:\> Get-Content -Encoding UTF8 -Path .\decoded2.txt
('~'|%  {  ${##########} <# 省略 #> "${###########}"]  }  );  &${##########} <# 省略 #>
PS C:\>

セミコロンは改行をあらわす文字です。また、アンパサンド記号に続くInvoke-Expressionやpowershell.exeなどに相当すると考えられる文字列にドル記号がついています。ドル記号はPowerShellにおいて変数をあらわすプレフィックスであるため、変数${##########}Invoke-Expressionやpowershell.exeに相当する文字列であると考えられます。よって、セミコロンより前の部分をコピーしてpowershell.exeに張り付けた後に、${##########}の中身を表示しましょう。

PS C:\> ('~'|%  {  ${##########}  =+$(  )}{  ${####}  =${##########}  }{  ${#######}=++${##########}  }{  ${#####}  =  ( <# 省略 #> {##########}  =  "$(  @{  })  "[  "${#######}"+  "${#########}"  ]  +"$(  @{})  "[  ${#########}]+"${##########}"["${#####}"+"${###########}"]  }  )
PS C:\> ${##########}
iex
PS C:\>

推測通り、Invoke-Expressionのエイリアスである「iex」という文字列が出力されました。よって、&${##########}に続く部分をコピーして、powershell.exeに張り付ければ難読化される前のスクリプトが出力できると考えられます。

PS C:\> ("  ${##########}  (  ${#}${#########}${####}+${#}${###########}${######}  +  ${#}${#######}${####}${#######}  +  <# 省略 #> ${#}${#######}${#######}${###########}+${#}${#######}${####}${######}  +  ${#}${#######}${####}${######})  "  ) | Add-Content -Encoding UTF8 -Path decoded3.txt
PS C:\> Get-Content -Encoding UTF8 -Path .\decoded3.txt
  iex  (  [CHar]40+[CHar]78  +  [CHar]101  +  [CHar]119  +[CHar]45+  [CHar]79  +  [CHar]98  +  [CHar]106+[CHar]101  +[CHar]99  +[CHar]116+[CHar]32+[CHar]45  +  [CHar]67+[CHar]111  +  [CHar]109  +  [CHar]79+[CHar]98+  [CHar]106+[CHar]101+  [CHar]99+[CHar]116  +  [CHar]32+  [CHar]87+  [CHar]83+[CHar]99+  [CHar]114+  [CHar]105  +[CHar]112+  [CHar]116+[CHar]46  +[CHar]83+[CHar]104+[CHar]101+[CHar]108  +  [CHar]108+  [CHar]41+  [CHar]46+  [CHar]80  +[CHar]111  +[CHar]112  +  [CHar]117+[CHar]112+[CHar]40+  [CHar]34+  [CHar]72+  [CHar]105  +  [CHar]32  +[CHar]58+[CHar]41+[CHar]34 +[CHar]44+  [CHar]32  +  [CHar]49  +[CHar]48+  [CHar]44  +  [CHar]32+[CHar]34  +  [CHar]72  +[CHar]97+[CHar]99  +  [CHar]107  +[CHar]101  +[CHar]100+  [CHar]33+[CHar]34  +[CHar]44+  [CHar]32+[CHar]51+[CHar]41  +[CHar]32  +  [CHar]124+[CHar]32+  [CHar]79  +  [CHar]117+[CHar]116  +  [CHar]45  +[CHar]78  +  [CHar]117+[CHar]108  +  [CHar]108)
PS C:\>

またもや難読化されたスクリプトが出現しました。冒頭にiexがあることは一目瞭然であるので、iexを除いた部分をコピーしてpowershell.exeに張り付けて出力しましょう。

PS C:\> (  [CHar]40+[CHar]78  +  [CHar]101  +  [CHar]119  +[CHar]45+  [CHar]79  +  [CHar]98  +  [CHar]106+[CHar]101  +[CHar]99  +[CHar]116+[CHar]32+[CHar]45  +  [CHar]67+[CHar]111  +  [CHar]109  +  [CHar]79+[CHar]98+  [CHar]106+[CHar]101+  [CHar]99+[CHar]116  +  [CHar]32+  [CHar]87+  [CHar]83+[CHar]99+  [CHar]114+  [CHar]105  +[CHar]112+  [CHar]116+[CHar]46  +[CHar]83+[CHar]104+[CHar]101+[CHar]108  +  [CHar]108+  [CHar]41+  [CHar]46+  [CHar]80  +[CHar]111  +[CHar]112  +  [CHar]117+[CHar]112+[CHar]40+  [CHar]34+  [CHar]72+  [CHar]105  +  [CHar]32  +[CHar]58+[CHar]41+[CHar]34 +[CHar]44+  [CHar]32  +  [CHar]49  +[CHar]48+  [CHar]44  +  [CHar]32+[CHar]34  +  [CHar]72  +[CHar]97+[CHar]99  +  [CHar]107  +[CHar]101  +[CHar]100+  [CHar]33+[CHar]34  +[CHar]44+  [CHar]32+[CHar]51+[CHar]41  +[CHar]32  +  [CHar]124+[CHar]32+  [CHar]79  +  [CHar]117+[CHar]116  +  [CHar]45  +[CHar]78  +  [CHar]117+[CHar]108  +  [CHar]108) | Add-Content -Encoding UTF8 -Path decoded4.txt
PS C:\> Get-Content -Encoding UTF8 -Path .\decoded4.txt
(New-Object -ComObject WScript.Shell).Popup("Hi :)", 10, "Hacked!", 3) | Out-Null
PS C:\>

ようやく平文のスクリプトを出力することに成功しました。結果のスクリプトはメッセージボックスを10秒間出力するだけのスクリプトです。

Invoke-Obfuscation

PowerShellスクリプトを難読化するツールとして、Invoke-ObfuscationがDaniel Bohannon (@danielhbohannon) によって公開されています。

github.com

本記事の解析対象として用意したスクリプトは、一部はInvoke-Obfuscationを用いて作成しました。より深くPowerShellの難読化について学びたい場合は、Daniel Bohannonの講演資料と共にInvoke-Obfuscationを活用するとよいでしょう。

まとめ

本記事は過去の記事のおさらいとして、難読化されたPowerShellスクリプトを平文化する手順について解説しました。一連の記事が、情報セキュリティ担当者の役に立てれば幸いです。

PowerShell難読化の基礎 (3)

概要

前回の記事および前々回の記事に引き続き、今回もPowerShellの難読化の手法について記述します。

コメントアウトの挿入による難読化

前回の記事ではバッククオート記号の挿入による難読化手法を取り上げましたが、コメントアウトを挿入することによってもコードの可読性を下げることが可能です。例として前々回の記事で作成した以下のコードを考えます。

(((102, 111, 114, 101, 97, 99, 104, 40, 36, 105, 32, 105, 110, 32, 40, 49, 46, 46, 53, 41, 41, 123, 32, 87, 114, 105, 116, 101, 45, 72, 111, 115, 116, 32, 36, 105, 125) | %{ ([Int]$_ -as [char]) }) -Join '') | &($env:comspec[4,15,25] -Join '')

以上の難読化されたコードは、1から5の数字を順に出力するものです。

PS C:\> (((102, 111, 114, 101, 97, 99, 104, 40, 36, 105, 32, 105, 110, 32, 40, 49, 46, 46, 53, 41, 41, 123, 32, 87, 114, 105, 116, 101, 45, 72, 111, 115, 116, 32, 36, 105, 125) | %{ ([Int]$_ -as [char]) }) -Join '') | &($env:comspec[4,15,25] -Join '')
1
2
3
4
5
PS C:\>

PowerShellでは<#と#>で括ることにより、複数行をコメントアウトすることが可能です。この性質を利用して、コードに意図的にコメントアウトを挿入することにより、可読性を低下させることができます。例えば以下のように挿入します。

(((102, 111, <# #>114, 101, 97, <# ;asjfasjfaa #>99, 104, 40, 36, 105, <# caf3tr#Dfnc #>32, 105, 110, 32, 40, 49, 46, 46,<# KNbceHrc #> 53, 41, 41, 123, 32, 87, 114, 105, 116, 101, 45, 72, <# 35u89uj0n0 #>111, 115, 116, 32, 36, 105, 125) | %{ ([Int]$_ -as [char]) }) -Join<# TGceWcc #> '') | &($env:comspec<# nuEbcGR53 #>[4,15,25] -Join '')

このコードをPowerShellで実行すると、以下のように正常に1から5までの数字が出力されます。

PS C:\> (((102, 111, <# #>114, 101, 97, <# ;asjfasjfaa #>99, 104, 40, 36, 105, <# caf3tr#Dfnc #>32, 105, 110, 32, 40, 49, 46, 46,<# KNbceHrc #> 53, 41, 41, 123, 32, 87, 114, 105, 116, 101, 45, 72, <# 35u89uj0n0 #>111, 115, 116, 32, 36, 105, 125) | %{ ([Int]$_ -as [char]) }) -Join<# TGceWcc #> '') | &($env:comspec<# nuEbcGR53 #>[4,15,25] -Join '')
1
2
3
4
5
PS C:\>

コメントアウトは意味のある文字列の間に挟むことはできません。たとえば「$test = "Get-Host"; Invoke-Expression $test」というコードに、以下のようにコメントアウトを挿入するとエラーになります。

PS C:\> $test = "Get-Host"; Invoke-Expr<# aaaa #>ession $test
Invoke-Expr<# : The term 'Invoke-Expr<#' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:21
+ $test = "Get-Host"; Invoke-Expr<# aaaa #>ession $test
+                     ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Invoke-Expr<#:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

PS C:\>

コメントアウトを挿入する場合は、以下のように語句の区切りに適切に挿入する必要があります。

PS C:\> $test = <# aaaa #>"Get-Host"; <# bbbb #>Invoke-Expression <# cccc #>$test


Name             : ConsoleHost
Version          : 5.1.17134.228
InstanceId       : 75c394c9-bdca-46bb-9ddc-189ca01897f0
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-US
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace



PS C:\>

Base64エンコードによる難読化

JavaScriptPHPなどでの難読化と同様に、PowerShellの難読化にもBase64エンコードが用いられます。

コマンドレットのBase64エンコード

PowerShellで実行するコマンドレットをBase64エンコードする手順から解説します。例として「Get-Date -Format G」を取り扱います。 まずはPowerShellのコマンドレットを適切な文字エンコードで読み取ります。Windows OSにおいてはUnicodeを標準として取り扱っているため、実行させたいコマンドの文字列をUnicodeのバイト列に変換する必要があります。文字列をUnicodeのバイト列に変換するには、名前空間System.TextのEncodingクラスに属しているUnicode.GetBytesメソッドを用います。

PS C:\> $com = "Get-Date -Format G"
PS C:\> $unicodeBytes = [System.Text.Encoding]::Unicode.GetBytes($com)
PS C:\> 

コマンドレットをUnicodeのバイト列に変換したら、名前空間SystemのCovertクラスに属しているToBase64Stringメソッドにより、Base64エンコードされた文字列を取得することができます。

PS C:\> [System.Convert]::ToBase64String($unicodeBytes)
RwBlAHQALQBEAGEAdABlACAALQBGAG8AcgBtAGEAdAAgAEcA
PS C:\> 

攻撃者はBase64エンコードされた文字列を実行する際に、powershell.exeを用いてコードの実行を試みます。powershell.exeにはBase64エンコードされた文字列をコマンドとして実行する、EncodedCommandというオプションがあります。ただし、powershell.exeのオプションは他のオプションと混同しない範囲で省略することが可能であるため、「powershell.exe -EncodedCommand ~」と用いられることはあまりなく、「powershell.exe -enc ~」のように用いられることがほとんどです。先ほどエンコードした文字列を実行すると、以下のように「Get-Date -Format G」の実行結果を得ることができます。

PS C:\> Get-Date -Format G
9/14/2018 2:14:50 PM
PS C:\> powershell.exe -enc RwBlAHQALQBEAGEAdABlACAALQBGAG8AcgBtAGEAdAAgAEcA
9/14/2018 2:14:59 PM
PS C:\> 

UnicodeではなくASCIIで変換した場合についても示します。先ほど説明した通り、Windows OSではUnicodeを標準で取り扱うため、ASCIIのバイト列としてBase64エンコードした文字列を実行しようとしてもうまくいきません。以下に実行例を示します。

PS C:\> $com = "Get-Date -Format G"
PS C:\> $asciiBytes = [System.Text.Encoding]::ASCII.GetBytes($com)
PS C:\> [System.Convert]::ToBase64String($asciiBytes)
R2V0LURhdGUgLUZvcm1hdCBH
PS C:\> powershell.exe -enc R2V0LURhdGUgLUZvcm1hdCBH
敇⵴慄整ⴠ潆浲瑡䜠 : The term '敇⵴慄整ⴠ潆浲瑡䜠' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ 敇⵴慄整ⴠ潆浲瑡䜠
+ ~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (敇⵴慄整ⴠ潆浲瑡䜠:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

PS C:\>

スクリプトBase64エンコード

スクリプトソースコードBase64エンコードする手順についても解説します。とはいえ、コマンドレットをBase64エンコードする手順と大差ありません。例として以下のスクリプトを用います。

PS C:\> Get-Content .\test.ps1
$namelist = @("John", "Alex", "Mike")

ForEach($name in $namelist)
{
    Write-Host ("Hello, " + $name + "!")
}
PS C:\> .\test.ps1
Hello, John!
Hello, Alex!
Hello, Mike!
PS C:\>

まずは名前空間System.IOのFileクラスから、ReadAllTextメソッドを用いてスクリプトファイルの内容をすべて読み取ります。

PS C:\> $filepath = "C:\test.ps1"
PS C:\> $srctext = [System.IO.File]::ReadAllText($filepath)
PS C:\>

あとは先ほどのコマンドレットと同じ手順で、Base64化されたスクリプトソースコードを得ることができます。

PS C:\> $unicodeBytes = [System.Text.Encoding]::Unicode.GetBytes($srctext)
PS C:\> [System.Convert]::ToBase64String($unicodeBytes)
JABuAGEAbQBlAGwAaQBzAHQAIAA9ACAAQAAoACIASgBvAGgAbgAiACwAIAAiAEEAbABlAHgAIgAsACAAIgBNAGkAawBlACIAKQANAAoAIAANAAoARgBvAHIARQBhAGMAaAAoACQAbgBhAG0AZQAgAGkAbgAgACQAbgBhAG0AZQBsAGkAcwB0ACkADQAKAHsADQAKACAAIAAgACAAVwByAGkAdABlAC0ASABvAHMAdAAgACgAIgBIAGUAbABsAG8ALAAgACIAIAArACAAJABuAGEAbQBlACAAKwAgACIAIQAiACkADQAKAH0A
PS C:\> powershell.exe -enc JABuAGEAbQBlAGwAaQBzAHQAIAA9ACAAQAAoACIASgBvAGgAbgAiACwAIAAiAEEAbABlAHgAIgAsACAAIgBNAGkAawBlACIAKQANAAoAIAANAAoARgBvAHIARQBhAGMAaAAoACQAbgBhAG0AZQAgAGkAbgAgACQAbgBhAG0AZQBsAGkAcwB0ACkADQAKAHsADQAKACAAIAAgACAAVwByAGkAdABlAC0ASABvAHMAdAAgACgAIgBIAGUAbABsAG8ALAAgACIAIAArACAAJABuAGEAbQBlACAAKwAgACIAIQAiACkADQAKAH0A
Hello, John!
Hello, Alex!
Hello, Mike!
PS C:\>

Base64エンコードされたコードのデコード

Base64エンコードされたコードをデコードする場合は、エンコードする手順とは逆の行程でデコードします。Base64エンコードされたコマンドをUnicodeのバイト列に変換する場合は名前空間SystemのConvertクラスに属するFromBase64Stringメソッドを、バイト列をUnicode文字列に変換するには名前空間System.TextのEncodingクラスに属するUnicode.GetStringメソッドを用います。

PS C:\> $encoded = "JABuAGEAbQBlAGwAaQBzAHQAIAA9ACAAQAAoACIASgBvAGgAbgAiACwAIAAiAEEAbABlAHgAIgAsACAAIgBNAGkAawBlACIAKQANAAoAIAANAAoARgBvAHIARQBhAGMAaAAoACQAbgBhAG0AZQAgAGkAbgAgACQAbgBhAG0AZQBsAGkAcwB0ACkADQAKAHsADQAKACAAIAAgACAAVwByAGkAdABlAC0ASABvAHMAdAAgACgAIgBIAGUAbABsAG8ALAAgACIAIAArACAAJABuAGEAbQBlACAAKwAgACIAIQAiACkADQAKAH0A"
PS C:\> $unicodeBytes = [System.Convert]::FromBase64String($encoded)
PS C:\> [System.Text.Encoding]::Unicode.GetString($unicodeBytes)
$namelist = @("John", "Alex", "Mike")

ForEach($name in $namelist)
{
    Write-Host ("Hello, " + $name + "!")
}
PS C:\>

まとめ

過去2回の記事に引き続き、今回の記事でもPowerShellの難読化手法について記述しました。次回の記事では難読化されたPowerShellの難読化を解除する手順について解説します。