contents
- はじめに
- FileFixが仕掛けられたWebサイト
- ユーザーに実行させるPowerShellコマンド
- 外部サーバーからダウンロードされるVBScriptファイル
- VBScriptから呼び出されるPowerShellコマンドとステガノグラフィ
- Reflective Code Loadingで実行される.NETローダー
- Lumma Stealerに実装された難読化手法
- 情報窃取とC&Cサーバーへの送信
- まとめ
はじめに
ClickFixと呼ばれる攻撃手法が2024年3月頃から確認され、その後サイバー攻撃において広く悪用されています。ClickFixはソーシャルエンジニアリングに分類される攻撃手法です。偽の認証画面や警告画面などを表示し、画面に示した指示をユーザーに実行させます。その結果、不正なコマンドが実行され、マルウェアの感染や認証情報の窃取などの被害につながります。ClickFixの技術的な解説については、2024年12月 マルウェアレポートで紹介しています。
ClickFixは画面に表示する内容やユーザーにコマンドを実行させる方法の違いによって、多くの亜種が確認されています。ただし多くの場合、ユーザーに悪性のコマンドを実行させるという点で共通しています。
ClickFixの亜種の1つとして、2025年11月 マルウェアレポートではFileFixと呼ばれる攻撃手法について取り上げました。FileFixとは、ファイルを開かせる操作を装ってユーザーに指示を与え、ユーザー自身に悪意のあるコマンドを実行させる手法です。このレポートの中で、ユーザーにコマンドを実行させるまでの流れや、実行されるコマンドの処理内容について解説しました。レポートでは紹介できなかった詳細な調査によって、このコマンドを実行すると最終的に情報窃取型のマルウェアであるLumma Stealerに感染する可能性があることが判明しました。
本レポートでは、上記のFileFixにだまされたユーザーが悪性コマンドを実行してからLumma Stealerに感染するまでの流れを中心に、技術的な視点で解説します。組織の従業員がFileFixの手法にだまされてマルウェア感染する状況の一例として知っていただき、FileFixを含むClickFixによる被害を回避するための一助となれば幸いです。
FileFixが仕掛けられたWebサイト
本節では、2025年11月 マルウェアレポートで紹介したFileFixについて、ユーザーに悪性コマンドを実行させるまでの流れを改めて解説します。
図 2はFileFixが仕組まれた悪意のあるWebサイトを示しています。このWebサイトには、アカウントが規定に準拠していないので現在利用不可であり、その状況を解消するためには手順に沿って審査をリクエストする必要がある、という趣旨の記載が確認できます。
図 2中の「Request a Review」のボタンをクリックすると、図 3に示した画面が表示されます。この画面上では、「Identity.pdf」という名称のファイルを開き、必要事項を入力するよう求められます。
図 3において要求される具体的な操作手順は以下のとおりです。
① 「Copy」ボタンをクリックしてファイルパスをコピーする
② 「Open File Explorer」ボタンをクリックしてエクスプローラーを開き、アドレスバーを選択した状態にする
③ 手順①でコピーしたファイルパスをアドレスバーに貼り付け、「Enter」キーを押す
④ ファイルが開かれたら必要事項を入力する
上記の手順③において、エクスプローラーのアドレスバーにファイルパスを貼り付けた様子を図 4に示します。アドレスバーの部分を確認すると、ファイルパスとして「Identity.pdf」が選択されているように見えます。しかし実際には悪性のPowerShellコマンドが貼り付けられており、指示に従って「Enter」キーを押すとそのコマンドが実行されてしまいます。
ユーザーに実行させるPowerShellコマンド
エクスプローラーのアドレスバーに貼り付けられるコマンドの全容を図 5に示します。このコマンドによって、以下の処理が実行されます。
① 外部のサーバーからVBScriptファイルをダウンロードし、「drv.pfx.vbs」というファイル名で一時フォルダに保存する
② VBScriptファイルをwscript.exeから呼び出して実行する
③ ユーザーをだますために偽のエラーメッセージを表示する
④ 300秒の遅延を挟んだ後、VBScriptファイルを削除する
図 5を確認すると、VBScriptファイルのダウンロードURLは直接記述されていません。変数「$b」に格納されたバイト列に対して、変数「$k2534=241(0xF1)」をキーとするXOR演算を行い、その結果を文字列に変換するという処理を経て復号されます。
コマンドの最後には処理の中で一度も使用されない変数「$i」が定義されています。この変数は大量の空白文字と「Identity.pdf」のファイルパスから構成される文字列データです。すでに示した図 4からも確認できるように、この変数はエクスプローラーのアドレスバーにPowerShellのコマンドが貼り付けられたことを隠ぺいする狙いがあると考えられます。
外部サーバーからダウンロードされるVBScriptファイル
前述のPowerShellコマンドによって外部からダウンロードされる「drv.pfx.vbs」について解説します。まずは図 6にVBScriptファイルの先頭付近のコードを示します。
図 6から確認できるように、このファイルは難読化されたVBScriptで構成されています。多くの難読化テクニックが使われており、例えばジャンクコード(使用されないコードや意味のないコード)やダミーコメントの挿入、無意味で長大な変数名、文字列の分割と結合などが挙げられます。また図 7に示したように、標準関数Chr()を複雑な処理でラップした独自関数を使用するなど、実際には単純な処理を関数化して何度も呼び出すような実装も確認できました。
図 8に示したように、このVBScriptは最終的にWshShellオブジェクトのRunメソッドを使用して新たなPowerShellコマンドを実行します。
VBScriptから呼び出されるPowerShellコマンドとステガノグラフィ
前述の図 8に示したPowerShellコマンドは、変数「$ddsdgo」に格納されたデータから文字列置換とBase64デコードを経て実際のコマンド文字列を復元し、そのコマンド文字列をiex(Invoke-Expressionのエイリアス)に渡します。復元されるコマンド文字列を図 9に示します。
図 9に示したコマンドは、大きく3つの段階の処理を実行します。それぞれの処理について解説します。
- 外部サーバーから画像ファイルをダウンロード
最初の処理段階では、配列「$links」に格納された2つのURLに対してランダムにアクセスし、「test.jpg」というファイル名の画像ファイルをダウンロードします。2つのURLのドメインはそれぞれ「bitbucket.org」と「raw.githubusercontent.com」であり、どちらもソースコードを管理あるいは共有する正規のサービスです。正規のサービスが提供するドメインやURLは、拒否リストへの登録が難しく、通信を検知しても不審な挙動と判別しにくいため、攻撃者がマルウェアのホスト先として悪用する場合があります。
調査時点で取得できた画像ファイルを図 10に示します。このファイルは通常の画像データと同様に画像ビューワーで開くことができますが、データの内部にマルウェアのペイロードを隠ぺいしています。 - ステガノグラフィを悪用したペイロードの抽出
次の処理段階では、画像ファイルからマルウェアのペイロードを抽出します。画像ファイルをバイナリエディタで開いた様子を図 11に示します。 図 11を確認すると、「<<BASE64_START>>」と「<<BASE64_END>>」という文字列を含むBase64エンコードされたデータが、通常の画像データの末尾に存在していることがわかります。図 9で示したPowerShellコマンドでは、「<<BASE64_START>>」および「<<BASE64_END>>」の文字列をスキャンし、それらに囲まれたBase64エンコードデータを抽出してデコードするという手順で、マルウェアのペイロードを画像データから取り出します。 - Reflective Code Loadingによるペイロードのファイルレス実行
最後の処理段階では、抽出したペイロードをReflective Code Loadingの手法を
利用してPowerShellプロセスのメモリー上にロードします。このペイロードは.NETで作成されたプログラムであり、メモリーにロードされた後のコマンドによって「testpowershell」名前空間に存在する「Hoaaaaaasdme」クラスの「lfsgeddddddda」メソッドが呼び出されます。この際、図 12に示した5つの引数が渡されます。
Reflective Code Loadingで実行される.NETローダー
Reflective Code Loadingによってメモリー上に展開されるペイロードは、追加のマルウェアを感染させるためのローダーです。このローダーの中で、PowerShellコマンドから呼び出される「Hoaaaaaasdme.lfsgeddddddda」メソッドのコードを図 13に示します。
「Hoaaaaaasdme.lfsgeddddddda」メソッドの処理を進めていくと、図 14に示したように追加のマルウェアペイロードをダウンロードします。ダウンロードURLは、「Hoaaaaaasdme.lfsgeddddddda」メソッドの実行時に渡された第一引数の文字列をもとに生成されます。ダウンロードされるペイロードは反転、置換、Base64デコードによって変換されます。その後、「Progrgdfam3.Tools3.Ande3」メソッドが実行されます。
「Progrgdfam3.Tools3.Ande3」メソッドには、Process Hollowingと呼ばれるインジェクション手法で前述のペイロードを実行する処理が定義されています。図 15から、今回の検体の場合、CreateProcessAのAPIを使用してRegAsm.exeのプロセスを作成することが確認できます。その後、図 16に示したWow64GetThreadContext、ReadProcessMemory、ZwUnmapViewOfSection、VirtualAllocEx、WriteProcessMemory、Wow64SetThreadContext、ResumeThreadのAPIを順に呼び出して、RegAsm.exeのメモリー上でペイロードを実行します。
Lumma Stealerに実装された難読化手法
今回の調査時点において、前述の図 14の通信処理でダウンロードを試みるファイル(Ahhiidb.txt)を取得することはできませんでした。ただし図 17に示すように、同一のディレクトリにホストされた別のファイル(AdbnjFa.txt)を確認することができました。このファイルは同一の攻撃者が用意した可能性が高く、攻撃者にとっては.NETローダーの「Hoaaaaaasdme.lfsgeddddddda」メソッドに渡す引数を変更するだけで容易にペイロードの変更が可能です。
Ahhiidb.txtの代わりにAdbnjFa.txtがダウンロードされる環境を用意して、FileFixが仕掛けられたWebサイトの操作手順を実行したところ、エラーなどの問題は発生せずにAdbnjFa.txtの処理が進むことを確認しました。
以上を踏まえ、本稿ではAhhiidb.txtの代わりにAdbnjFa.txtがダウンロードされる想定で、AdbnjFa.txtを解析した内容について紹介します。
AdbnjFa.txtは情報窃取型のマルウェアに分類されるLumma Stealerです。この検体には、多くの難読化手法が用いられています。実装されている手法の例を紹介します。
独自のデータ変換処理
本検体には、単純な演算を複雑に実装したデータ変換処理が随所に存在します。このデータ変換処理の例を図 18に示します。
図 18の例1では、XOR演算に使用されるキーの値が変数iの値によって変動します。また例2の場合、XORキーの難読化に加えて、forループのインクリメント処理を複雑化することで、変数iの値も難読化しています。
API hashing
本検体では一部のAPIについて、API hashingの手法で動的に解決していることを確認しました。例として、図 19にAPI hashingを使用してRtlFreeHeapを呼び出す処理を示します。ハッシュ値がエンコードされている場合は、前述のデータ変換処理でデコードしてからAPIの解決を行います。エンコードされていない場合、データ変換処理を介さずに直接APIの解決を行います。
検体で確認できたAPIの一覧を表 1に示します。
表 1 API hashingによって動的に解決されるAPIの一覧
| エンコードされたハッシュ値 | APIに対応するハッシュ値 | API名 |
|---|---|---|
| - | 0x141F8E35 | CloseDesktop |
| - | 0xACFAAFF8 | CoCreateInstance |
| - | 0x7DF01250 | CreateDesktopW |
| - | 0x8D95287B | CreateProcessW |
| - | 0x930CD765 | CreateThread |
| - | 0x3193C2CB | CryptUnprotectData |
| - | 0xCAA315F0 | EnumDisplaySettingsW |
| 0x1BF2AB7E | 0x7C540EE2 | FreeLibrary |
| 0xB7CE0752 | 0x7C540EE2 | FreeLibrary |
| 0xF7DE1B4E | 0x7C540EE2 | FreeLibrary |
| 0x173EFB8E | 0x7C540EE2 | FreeLibrary |
| 0x6F469BF6 | 0x7C540EE2 | FreeLibrary |
| 0xB7CE0752 | 0x7C540EE2 | FreeLibrary |
| - | 0xDB23EF00 | GetComputerNameA |
| - | 0x0C01F727 | GetComputerNameExA |
| - | 0x154150E3 | GetPhysicallyInstalledSystemMemory |
| - | 0x20295A69 | GetProcAddress |
| - | 0xE49E113C | GetUserDefaultLocaleName |
| - | 0x8CED6615 | GetUserDefaultUILanguage |
| - | 0xD94B8B86 | GetUserNameA |
| - | 0x8329D76E | GetVolumeInformationW |
| - | 0xF7A922CF | IsWow64Process |
| 0x674A5F86 | 0x907486AE | LoadLibraryExW |
| 0xCFAAB7EE | 0x907486AE | LoadLibraryExW |
| 0xEB8693CA | 0x907486AE | LoadLibraryExW |
| 0x33D6C72E | 0x907486AE | LoadLibraryExW |
| - | 0xCC4A769D | LoadLibraryW |
| - | 0xDD76139A | LocalFree |
| - | 0xDD749658 | LookupPrivilegeValueW |
| - | 0xE11E08C4 | OpenDesktopW |
| 0xB9911868 | 0xCEA52B9C | RtlAllocateHeap |
| 0xCE5AA0D3 | 0x47B42B39 | RtlFreeHeap |
| - | 0x3998FE85 | RtlOpenCurrentUser |
| - | 0xFEA2C3C5 | RtlReAllocateHeap |
| - | 0x58BD1BB9 | WinHttpAddRequestHeaders |
| 0x06618A07 | 0x0FA9810D | WinHttpCloseHandle |
| - | 0x9C300F61 | WinHttpConnect |
| - | 0xE3DB255A | WinHttpCrackUrl |
| - | 0x9FEB9D71 | WinHttpOpen |
| - | 0xFC1D2D06 | WinHttpOpenRequest |
| - | 0xDF32E76A | WinHttpQueryDataAvailable |
| - | 0x0C3E873B | WinHttpQueryHeaders |
| - | 0x3393ABAD | WinHttpReadData |
| - | 0xF671DC7D | WinHttpReceiveResponse |
| - | 0xD7A0E738 | WinHttpSendRequest |
| - | 0x21B03CD6 | WinHttpSetOption |
| - | 0xCF43BDCF | WinHttpSetTimeouts |
| - | 0xA78479AC | WinHttpWriteData |
またWindowsのNTAPI関数についても、API hashingを利用して動的に呼び出されることを確認しました。例として、NtQuerySystemInformationを呼び出す部分のコードを図 20に示します。
NTAPIを呼び出す流れとして、はじめに、APIのハッシュ値とシステムコール番号の対応表から特定のハッシュ値を探索します。続いて、該当するハッシュ値が対応表の中に存在する場合、そのハッシュ値と対になるシステムコール番号を取り出します。最後に、取り出したシステムコール番号とNTAPI実行時の引数を、システムコールを呼び出すラッパー関数に渡します。
Windowsの場合、OSのビルド番号によってシステムコール番号が変動するAPIがあるため、ハッシュ値とシステムコール番号の対応表は動的に作成されます。この対応表の例を図 21に示します。また検体から確認できたNTAPIの一覧を表 2に示します。
表 2 API hashingによって動的に解決されるNTAPIの一覧
| エンコードされたハッシュ値 | APIに対応するハッシュ値 | API名 |
|---|---|---|
| - | 0x0FB8D729 | NtAdjustPrivilegesToken |
| - | 0x6D603FE4 | NtAllocateVirtualMemory |
| - | 0x36B57D02 | NtAssignProcessToJobObject |
| - | 0x5A3C2B61 | NtClose |
| - | 0xA478E3A5 | NtCreateFile |
| - | 0xC6A34A35 | NtCreateIoCompletion |
| - | 0x431BF179 | NtCreateJobObject |
| - | 0x2D5FAC64 | NtCreateMutant |
| - | 0x7A0A33BE | NtCreateSection |
| - | 0x54E072A8 | NtDelayExecution |
| - | 0x46F9D31B | NtDuplicateObject |
| - | 0x0EB19E49 | NtDuplicateToken |
| 0x11CEE346 | 0x4214F28E | NtEnumerateKey |
| - | 0xCDF5CCDB | NtEnumerateValueKey |
| - | 0x68F5A4A3 | NtFreeVirtualMemory |
| - | 0x22E7F69A | NtMapViewOfSection |
| - | 0xE0D2DEF9 | NtOpenFile |
| - | 0x8C7E241B | NtOpenKeyEx |
| - | 0x853072B8 | NtOpenMutant |
| - | 0x95AD8334 | NtOpenProcess |
| - | 0x5E2F7D11 | NtOpenProcessToken |
| - | 0x72745742 | NtOpenSection |
| - | 0xCC930C1C | NtOpenThreadToken |
| - | 0x8682AA22 | NtProtectVirtualMemory |
| - | 0x97760426 | NtQueryAttributesFile |
| - | 0x915A74D2 | NtQueryDirectoryFile |
| - | 0x0A71D0EF | NtQueryInformationFile |
| - | 0x529D00F6 | NtQueryInformationProcess |
| - | 0x32ECAB1E | NtQueryInformationToken |
| - | 0x8DD87000 | NtQueryKey |
| - | 0x98E38976 | NtQuerySystemInformation |
| - | 0x460854CD | NtQueryValueKey |
| - | 0xF60E441B | NtQueryVirtualMemory |
| - | 0x6987715A | NtRaiseHardError |
| - | 0x53CD60A1 | NtReadFile |
| - | 0xA8679925 | NtReadVirtualMemory |
| - | 0xB91A4B97 | NtReleaseMutant |
| - | 0x953F5C61 | NtRemoveIoCompletion |
| - | 0x658620B0 | NtResumeThread |
| - | 0x7B2E8317 | NtSetInformationJobObject |
| - | 0x62981C16 | NtSetInformationProcess |
| - | 0xE26444DD | NtSetInformationThread |
| - | 0x842585F3 | NtTerminateProcess |
| - | 0xC67AEEF1 | NtUnmapViewOfSection |
| - | 0x734B49AA | NtWaitForSingleObject |
| - | 0x5D7BC928 | NtWriteFile |
間接ジャンプ
本検体のjmp命令の中には、ジャンプ先のアドレスを直接指定せず、埋め込みデータを介した形式で指定しているものがあることを確認しています。
図 22は、sub_445670サブルーチンの中で確認できる間接ジャンプの例を2つ示しています。図中のコードブロック①では、ジャンプ先としてoff_451690が指定されており、.dataセクションを確認するとoff_451690はloc_4456C0を示していることがわかります。これは単純化すると「jmp short loc_4456C0」という処理を表します。コードブロック②についても同様に、「jmp short loc_44599C」という処理を複雑化し、埋め込みデータを介した形式で実装されています。
図 22に示した実装の攻撃者視点でのメリットとして、例えば逆アセンブラのIDA Proの場合、逆コンパイル機能を使用した疑似コードの生成が不適切になり、解析を妨害することが可能である点が挙げられます。
図 23は、図 22と同様のsub_445670サブルーチンに対する逆コンパイルの実行結果を示しています。本来は図 22の左に示すように複数のコードブロックから構成されるサブルーチンですが、実際には図 22中のコードブロック①のみを不完全な形で逆コンパイルしてしまっていることがわかります。
より正確な解析をするためには、ジャンプ先のアドレスを直接指定する形式で修正パッチを適用する必要があります。パッチを適用すると、図 24に示すような逆コンパイル結果を得ることが可能です。
Control-flow Graph Flattening
前述の間接ジャンプに加えて、本検体はControl-flow Graph Flattening(Control Flow Flattening)と呼ばれる手法を悪用することでコードのフローをさらに複雑にしています。Control-flow Graph Flatteningとは、プログラムのブロックを1つの無限ループと大規模なswitch文の中に配置し、状態変数を使用して制御フローを構築することでプログラムの全体像を複雑にする手法です。
Control-flow Graph Flatteningについて、簡単な例を用いて説明します。図 25は、単純なif文のみで構成されたコード(左)と、そのプログラムを逆アセンブルした際の制御フロー(右)を示します。また比較対象として、図 25のコードにControl-flow Graph Flatteningの手法を用いて難読化した例を図 26に示します。図 26ではwhile(true)による無限ループの中にコードを挟み込み、さらに状態変数stateの値を変化させながらswitch文を使用してフローを複雑にしていることが確認できます。
上記の例では1つの状態変数とswitch文の組み合わせで説明しましたが、本検体においては複数の状態変数を使用し、switch文をネスト構造にすることでより複雑なフローにしています。
情報窃取とC&Cサーバーへの送信
本検体は感染端末からさまざまな情報を窃取して、C&C(Command and Control)サーバーにHTTPSのPOSTリクエストで送信します。このPOSTリクエストは複数回に分けて行われます。検体から送信される通信データの一例を図 27に示します。
POSTリクエストはmultipart/form-dataの形式で複数のデータを送信します。各データの区切りを表すboundaryの値(図 27中の①)には、MT19937の疑似乱数生成アルゴリズムを利用して生成したランダムな文字列が使用されます。
「uid」という名称で区別されているデータ(図 27中の②)は、検体のプログラム中に埋め込まれた固定値であることを確認しました。「pid」という名称で区別されているデータ(図 27中の③)は、送信する情報の種類に応じた固定の値であることを確認しました。「hwid」という名称で区別されているデータ(図 27中の④)は、感染端末に応じた固定値であることを確認しました。
それぞれの値が示す詳細な意味については断定できませんが、名称などから判断すると、「uid」は検体を識別するためのデータ、「pid」は窃取した情報の種類を識別するためのデータ、「hwid」は感染端末を識別するためのデータである可能性があります。
「file」という名称で区別されているデータ(図 27中の⑤)は、感染端末から窃取した情報です。窃取した情報はZIP形式で圧縮した後、ChaCha20のアルゴリズムによって暗号化されることを確認しました。図 28に示したように、このデータは暗号化した窃取データの末尾に、復号に必要な32バイトの共通鍵と8バイトのNonceを付加した形式で構成されます。送信データのみで復号が可能な構成を採用していることから、窃取した情報の機密性を確保することよりも、セキュリティ製品による検査で不審な通信と判定されることを防ぐ狙いが強いと考えられます。
上記の構成情報をもとに「file」のデータをChaCha20のアルゴリズムで復号した様子を図 29に示します。復号するとZIP圧縮データが出力され、展開すると端末から窃取した情報を記載したファイル(図 29の例では「Processes.txt」と「Software.txt」)が確認できます。
なお、復号に用いたPythonスクリプトは本レポート末尾の表 5に掲載しています。
検体で確認できた窃取対象の情報については表 3を参照してください。
表 3 感染端末から窃取する情報の一覧
| 以下のメールクライアントに保存された情報 |
|---|
| Outlook、Thunderbird、Windows Mail |
| 以下のアプリケーションに保存された情報 |
| Discord、Notepad++、Steam |
| 「Software.txt」のファイル名で保存される情報 |
| 端末にインストールされているソフトウェアの一覧 |
| 「Processes.txt」のファイル名で保存される情報 |
| 検体実行時の起動中プロセスの一覧 |
| 「System.txt」のファイル名で保存される情報 |
| 検体の作成年月日、検体の実行パス、OSのバージョン、検体の実行日時、感染端末のタイムゾーン、OSのインストール日時、権限昇格の有無、コンピューター名、ユーザー名、ドメイン名、ホスト名、NetBIOS名、システム言語、インストールされているアンチウイルスソフト、送信データに含まれる「hwid」の値、メモリーサイズ、CPUベンダー名、CPU名、CPUのスレッド数、CPUのコア数、GPU名、画面の解像度 |
| 「Clipboard.txt」のファイル名で保存される情報 |
| クリップボードにコピーされたデータ |
まとめ
本稿で解説したLumma Stealerに感染するまでの流れを図 30に示します。FileFixが仕掛けられたWebサイトにユーザーがアクセスし画面の指示に従うと、外部からのペイロード取得を3回実行しながら、Windowsの正規プログラムである「RegAsm.exe」にLumma Stealerがインジェクションされ、情報漏えいを引き起こします。
FileFixを含むClickFixの手法は日々巧妙化していますが、多くの場合に共通することはユーザー自身に悪性コマンドを実行させるという点です。ユーザーの心理的な隙を突くソーシャルエンジニアリングの手法であることから、まずはユーザーが攻撃手法を認知して、画面に表示された不審な指示に従わないよう注意することが重要です。そのため、組織のセキュリティ担当者は、セキュリティ製品の運用などの技術的な対策に加えて、従業員への攻撃手法の周知も行ってください。
表 4 検体のIoC情報
| HTMLファイルのSHA256ハッシュ |
|---|
| 9912ede354f69ac4e6eda1ad9c233790698ec3750e1a354b404fafbdb6a3a418 |
| VBScriptファイルのSHA256ハッシュ |
| 34eed23934dc449e840e80c3c5987c0dbea94ecb59703f428700c97d83a63524 |
| JPGファイルのSHA256ハッシュ |
| 97359cacc28e3c40cd9ffd4c44f41080ccbbcf23c8beebd445c55bedee7e30d7 |
| EXEファイル(.NETローダー)のSHA256ハッシュ |
| c5c8a9e547165bace57081f3759e7ff81fffbdb77b0357dfcebe2871c43008f2 |
| EXEファイル(Lumma Stealer)のSHA256ハッシュ |
| d8a5652052661b8278f792385c8bd48170a449d63672f5c78056a141194724b3 |
表 5 図 29の中で使用したデータ復号用のPythonスクリプト
Python
import argparse
from Crypto.Cipher import ChaCha20
def to_hexdump(data: bytes) -> str:
lines = []
for i in range(0, len(data), 16):
chunk = data[i:i+16]
hex_parts = [f"{b:02X}" for b in chunk]
if len(hex_parts) > 8:
hex_str = " ".join(hex_parts[:8]) + " " + " ".join(hex_parts[8:])
else:
hex_str = " ".join(hex_parts)
hex_str = hex_str.ljust(49)
ascii_str = "".join(chr(b) if 32 <= b <= 126 else "." for b in chunk)
lines.append(f"{i:08X}: {hex_str} |{ascii_str}|")
return "\n".join(lines)
def decrypt_data(enc_data):
key_hex = enc_data[-80:-16]
nonce_hex = enc_data[-16:]
ciphertext_hex = enc_data[:-80]
key = bytes.fromhex(key_hex)
nonce = bytes.fromhex(nonce_hex)
ciphertext = bytes.fromhex(ciphertext_hex)
cipher_decrypted = ChaCha20.new(key=key, nonce=nonce)
plaintext = cipher_decrypted.decrypt(ciphertext)
return plaintext
def main():
parser = argparse.ArgumentParser(description=("ChaCha20 POST data decryptor"))
parser.add_argument("enc_data", help="復号対象の16進数データ")
args = parser.parse_args()
decrypted = decrypt_data(args.enc_data)
with open("decrypted.bin", "wb") as f:
f.write(decrypted)
print("--- 復号結果 ---")
print(to_hexdump(decrypted))
if __name__ == "__main__":
main()































