> > 情報窃取マルウェア「Ryuk Stealer」の内部構造を紐解く

情報窃取マルウェア「Ryuk Stealer」の内部構造を紐解く

2020.02.18
コンサルティングサービス事業本部
サイバーインテリジェンスグループ
吉川 孝志
title1

前回の記事ではEmotetの先に見え隠れする「Ryuk」というランサムウェアについて述べましたが、今回はそのランサムウェア「Ryuk」に関連している可能性のある「Ryuk Stealer」というマルウェアに焦点を当てます。

Ryuk Stealerは、感染端末の中にある重要なファイルを収集/窃取するマルウェアであり、Ryukに関連した特徴を持つことから、ランサムウェア「Ryuk」と何らかの繋がりがあるとされています。
現時点でRyuk StealerがRyukの攻撃で使用されたことを示す明確な証拠は確認されていませんが、調査後の結論として、このマルウェアはRyukの攻撃に合わせて開発されているマルウェアである可能性が十分高いと考えられます。

想定される攻撃シナリオとしては、攻撃者がターゲット環境に侵入した後、あらかじめRyuk Stealerを使用して不正なファイルの収集/窃取を一通り実施した上でランサムウェア「Ryuk」による暗号化を行っているという可能性があげられます。
攻撃者がRyuk Stealerを使用する場合、少なくとも2つの目的が推測できます。1つ目は、ランサムウェアの被害者から効果的に身代金を要求するという目的です。たとえランサムウェアによる身代金を拒む被害者がいても、予めRyuk Stealerで窃取しておいた情報を流出させると脅すことで、身代金の支払いを強く促すことができます。2つ目は、そもそも情報の窃取が目的であり、Ryuk Stealerを使用して情報を盗んだ後にランサムウェアRyukを放つことで、情報窃取の証拠隠滅を行うというケースです。どちらも推測ではありますが、同じ攻撃で併用される場合はこうした目的がまずは考えうるでしょう。

最初のRyuk Stealerは2019年9月に初めてその存在が発見されましたが、2020年1月末になり、新たに別の検体が確認されました。今回はその最新のRyuk Stealerを中心に、過去のバージョンの検体との比較も織り交ぜながら解説していきます。


■表層解析

最新のRyuk Stealerは以下のようなアイコンとプロパティ情報を持っています。EXEファイルのPEヘッダから確認できるコンパイル日時は「2020-01-19 00:11:32」です。

図1 最新Ryuk Stealerのアイコンとプロパティ

以下はEXEファイルに埋め込まれたマニフェストですが、管理者権限での実行は特に設定されておらず、実行時の親プロセスと同じ権限で実行されます。後ほどまた解説しますが、実行時の第一引数に渡されたファイルパスを削除する機能を保有している為、何らかの別のキッカー(親プログラム)により実行され、キッカーを削除して証拠隠滅する等の挙動が可能です。その場合は、キッカーが管理者権限であれば、Ryuk Stealerもまた管理者権限で実行されることになります。

図2 EXEファイルに埋め込まれたマニフェスト

Ryuk StealerのEXEファイルには、デバッグ情報に関わるPDBファイルへのパスが埋め込まれています。このパスは開発者がデバッグする際に使用するデータベースであるPDBファイルを指しますが、普通にコンパイルしてしまうとEXEファイル内にパス文字列が埋め込まれてしまうため、意図的にパスを含ませないよう設定をした上でビルドする必要があります。そのためこのパス文字列が含まれている場合、マルウェア開発者のユーザー名や開発環境に関する情報が把握できるケースがあります。もちろん偽装することは可能ですが、多くは攻撃者の不注意で埋め込まれているケースが多いでしょう。
以下の図を見てわかるとおり、Ryuk Stealerは「Projects From Ryuk」というプロジェクト名で開発されており、Ryukという名の攻撃の一環で使用されるプログラムの一つであることを示唆する情報といえます。

図3 EXEファイルに埋め込まれた開発環境に関わる情報

最新のRyuk Stealerはファイルの構造上、一見すると正規プログラムのように装っていますが、メインの不正コードを3段階に暗号化して内部に保有しています。この際、Windows APIに存在するコールバック関数の仕組みを利用して、不正コードを3段階に展開(アンパック)し、最終的にメインとなる不正コードで元のコードを書き換えることで本来の不正動作を開始します。以下ではその仕組みを、一つずつ順を追って解説していきます。


■不可視ウインドウとコールバック関数の悪用による解析/検知妨害

過去に確認されたRyuk Stealerと異なり、最近確認されたRyuk Stealerは少し複雑なパッキング処理が施されており、マルウェアの解析や検知を妨害するアンチデバッグ(耐解析)テクニックとして、Windows APIにおけるコールバック関数の悪用を行なっています。最新Ryuk Stealerのこの点に関する解析情報は筆者の把握している限り世界的にも言及されていないようですので、本ブログでは少し踏み込んで解説します。

コールバック関数とは、あるAPIのパラメータとして渡しておくことで、そのAPIの呼び出しに紐づいて間接的に呼び出せることができる仕組みであり、一般的にWindowsにおけるメッセージやイベントの処理で使用されます。
Ryuk Stealerはこの仕組みを悪用し不正コードをコールバック関数として登録しておくことで、OSに不正コード(コールバック関数)を間接的に呼び出させ、コードの追跡を妨害するアンチデバッグ(耐解析)を行っています。

WindowsAPIにおけるコールバック関数は様々ありますが、Ryuk Stealerにおいてはウインドウを扱う際に使用する「RegisterClassEx」というAPIを利用しています。RegisterClassExはウインドウの機能を定義するために使用されるWindowクラスの名前を登録する関数であり、WNDCLASSEX構造体へのポインターを受け取る役割を持ちますが、その構成要素の中に、のちに作成するウインドウに送信されたメッセージを処理するコールバック関数を含ませることができます。Ryuk Stealerはこのコールバック関数に不正な処理を登録します。

まず、Ryuk Stealerは実行後、RegisterClassExを呼び出し、そのパラメータであるWNDCLASSEX構造体のコールバック関数(ウインドウプロシージャ)に不正コードを含む処理のアドレスを登録します。その後、CreateWindowExを使用してユーザーには見ることのできない不可視のウインドウを作成します。
なお、通常CreateWindowExを呼び出してウインドウを作成するだけでは表示されず(※作成するウインドウのスタイルにWS_VISIBLEが設定されていない場合)、作成したウインドウを明確に表示するためのShowWindowというAPIをセットで呼び出すことが一般的であり、Ryuk Stealerも例外なくShowWindowを呼び出します。しかし、Ryuk Stealerが作成するウインドウにはWS_VISIBLEが設定されておらず、また、ShowWindowのパラメータに渡されるハンドルが無効(NULL)かつ非表示(SW_HIDE)に設定されているため、ShowWindowの呼び出し後もウインドウは一切表示されません。つまりこの時点で、ユーザーには見えない不可視ウインドウが作成されていることになります。

図4 不可視ウインドウの作成

Windowsにおいては、何もしていなくてもあらゆるウインドウには様々な「ウインドウメッセージ」というものが随時OSからブロードキャストで送られてきます。例えば、あるウインドウの中でユーザーがマウスカーソルを動かした場合、そのウインドウには「WM_SETCURSOR(0x0020)」や「WM_MOUSEMOVE(0x0200)」というウインドウメッセージが送られ、ウインドウ内で右クリックをすれば「WM_RBUTTONDOWN(0x0204)」というウインドウメッセージが送られてくるといった具合です。WindowsのGUIプログラムは基本的にこのウインドウメッセージの処理で様々な動きが実現されています。

話を戻しますが、Ryuk Stealerが作成した不可視ウインドウになんらかのウインドウメッセージが送られてくるとOSにより自動的に上記の不正コードを含むコールバック関数が呼び出されます。

不正コードを含むコールバック関数が呼び出されると、不可視ウインドウに送信されてくるウインドウメッセージを分類し、「WM_CREATE(0x001)」および「WM_SIZE(0x005)」が送られてきた場合、それをトリガーにし、暗号化されていたデータの復号コードが呼び出されます。その結果、Ryuk Stealer本来の不正コードが復号され、元の実行可能領域に展開されることで、本来のRyuk Stealerが動き始めます。

図5 コールバック関数の呼び出しとウインドウメッセージを利用したデコード

以上まで解説した内容をできるだけシンプルに概念図として示したものが以下です。

図6 ウインドウメッセージを利用したアンパック処理の全体概要

ちなみに、この不可視ウインドウを強制的に表示させてみるとどのようなウインドウが見えるでしょうか。
以下のように、ShowWindowのパラメータをデバッガで無理やり書き換えてみます。不可視ウインドウを表示させる方法はいくつかありますが、今回はShowWindowの第1引数が不可視ウインドウのハンドル(CreateWindowExの戻り値)に、第2引数がSW_SHOWNORMAL(0x1)になるように書換えます。

図7 不可視ウインドウを表示させるように処理を改変

以上の方法で、Ryuk Stealerが作成する不可視ウインドウを無理やり表示させてみた結果が以下となります。これを見る限り、(マルウェアにとって)このウインドウが表示される意味を持たないことがわかります。

図8 不可視ウインドウを強制的に表示させてみた様子

■不可視ウインドウが作成された後のアンパック処理の流れ

不可視ウインドウが作成され特定のウインドウメッセージを受信すると不正コードが呼び出され、本来のRyuk Stealerとなる本体コードの復号処理が開始されますが、その際、3段階の復号ルーチンに分かれており、それらの処理の遷移を図示したものが以下の図です。(※なお以降の解説で触れるアドレスはASLR有効時のものであり、検証時の構成となる点予めご了承下さい)

図9 Ryuk Stealerの本体が展開されるまでの遷移

まず、1段階目の復号処理で、VirtualAllocExで確保した特定の実行コード領域に1段階目のデコード関数を復号し実行します(図9の①~⑥の流れが該当)。
以下の図は第一段階のデコード関数をメモリ上に復号している際の様子です(図9の⑥に該当)。

図10 第一デコード関数の復号

続いて、展開された1段階目のデコード関数により、同アドレス帯に2段階目のデコード関数とその展開コードが復号されます(以下の図は図9の⑦に該当)。

図11 2段階目のデコード関数を含む処理を復号

2段階目のデコード関数により、3段階目のデコード関数が呼び出され、Ryuk Stealerの実行モジュールが最初に読み込まれた実行領域のメモリが0で初期化されます(以下図は図9の⑨に該当)。

図12 3段階目のデコード関数により実行領域が初期化

その後、3段階目のデコード関数は内部に別途暗号化していたRyuk Stealerの本体コードを上記アドレスへ復号・上書きします。その結果、最終的に実行モジュールの元のアドレス帯にRyuk Stealerの本来の姿が現れます(以下図は図9の⑩に該当)。

図13 最後にRyuk Stealer本来のボディが復号され展開

以上の流れにより復号(アンパック)されたRyuk Stealerはメモリ上だけに存在し、実体のEXEファイルとは異なる構造に変化しますが、メモリ上に展開されたRyuk Stealerをメモリから直接ファイルに取り出すと、元のアイコンとは異なるアイコンを持つEXEファイルが抽出できます。これは、過去のRyuk Stealerのアイコンと同一であり、このことから、Ryuk Stealer本体が何らかのパッカー(EXEの暗号化ツール)によりパック(暗号化)されていたことが推測できます。

図14 Ryuk Stealerの本来のアイコンが出現

■Ryuk Stealerのメイン処理

ここでようやくRyuk Stealerの本来のメイン処理の解説に移ります。
Ryuk Stealerは実行されると、実行時の第一引数にファイルパスが指定されていた場合、そのファイルを削除する機能を持っています。この機能を攻撃者が実際にどう活用しているのかという点については推測となりますが、冒頭でも少し触れた通り、例えばRyuk StealerのEXEを実行する別の親プログラム(キッカー)が存在した場合、そのプログラムパスを第一引数に渡すことで実行後に削除することができ、追跡を困難にさせるなどの隠蔽用途が推測できます。

その後、感染端末で確認できる全てのドライブを列挙し、DriveType=5、つまりCD/DVDドライブ以外のドライブの全てのドライブを対象に特定のファイルを収集し、攻撃者の用意したFTPサーバへアップロードします。この際、ネットワーク上のフォルダなどをドライブマッピングしている場合は、それらネットワーク上のディレクトリ内のファイルも収集対象になります。

図15 Ryuk Stealerのメイン処理の一部

■FTPへのアップロード

Ryuk Stealerは盗んだファイルを1ファイルごとに25秒待機しながら少しずつFTPサーバへアップロードしていきます。

図16 スリープを挟み少しずつFTPサーバへアップロード

窃取したファイルを送信するFTPサーバは以下の2つのIPアドレスとディレクトリ名がハードコードされており、同じくハードコーディングされた特定のユーザー名とパスワードで接続します。

FTPサーバの接続先:

FTP先のディレクトリ名:

図17 特定のユーザー名&パスワードでFTPサーバへ接続

■窃取するファイルを選り好み

Ryuk Stealerは闇雲に全てのファイルを窃取するわけではなく、ファイル名やファイルの内容をもとに、より重要と思われるファイルを選り好みして収集します。

まず、特に価値の高い情報を含む可能性のある特定拡張子を持つファイルを重点的に収集対象とします。Office文章系ファイルやPDFなどが該当しますが、過去のバージョンにはなかった「cpp」や「h」などのプログラムの開発に関わる拡張子が収集対象に追加されています。

図18 重点的に窃取する拡張子

なお、過去バージョンのRyuk StealerはZIPファイルの圧縮解凍機能を提供するオープンソースのlibzipライブラリのモジュール「libzip.dll」を外部参照で使用し、docxおよびxlsxのファイル構造をチェックする機能を持っていました。
一般的なdocx/xlsxの文書ファイルはファイル構造がZIPファイルのフォーマットとなっているため、拡張子がdocxまたはxlsxであった場合、libzip.dllの関数によりZIP展開後の内部ファイルを調べ「word/document.xml」等のOffice文書ファイルとして必要な構成ファイルが内部に含まれているかどうかをチェックすることで、本物のdocx/xlsx文書ファイルであるかどうかを確認していました。
そのため、過去のRyuk Stealerでは拡張子がdocxであってもファイルの構造がdocxと異なる場合は窃取対象から除外されていましたが、最新のRyuk Stealerではこのチェック機構が排除され、拡張子がdocx/xlsxに一致すれば全て収集対象になるように変更されています。

図19 過去のRyuk Stealerのdocx/xlsxのファイル構造チェック

またRyuk Stealerは、ファイル名に特定の文字列を含むファイルを収集対象とします。
以下はRyuk Stealerがファイル名に対してチェックする収集対象の文字列リストですが、秘密情報に関わる単語やNATO、サイバー、防衛、政府、軍などの単語も見受けられます。

図20 ファイル名に含まれた場合に収集対象とする文字列リスト

さらにファイル名だけでなく、ファイルの内部に下図に示す文字列があるファイルも窃取対象にします。上に挙げた秘密関連や軍・政府などの単語に加え、工業やファイナンスなどの単語も並んでいることがわかります。
これに繋がるような話として、今年1月末にも軍事/製造に関わる米国政府の請負企業がランサムウェア「Ryuk」の被害にあったというニュースが報じられており、Ryuk Stealerが収集対象とする情報と合致すると捉えることもできます。
また興味深い点として、いくつかの人名が含まれており、これらは米国の新生児の2018年度ランキングの並びとほぼ一致します。この背景としては、一般的に子供に関わるデータは非常に重要である場合が多く、攻撃者が何らかの弱みを握る為、子供に関するファイルを収集しているという可能性がその一つに考えられます。例えば、ランサムウェアによる暗号化の被害データにこうした子供に関わるものが含まれた場合、被害者にとってダメージは非常に大きく、身代金の支払い率をより高められるメリットが攻撃者にあるとも言えそうです。

図21 ファイルの中身に含む場合に収集対象とする文字列リスト

以下は実際に検証環境で動作させ確認した様子ですが、特定の文字列を内部に含むファイルが検索され、FTPサーバへアップロードされていることがわかります。(※本検証はアクセス先の不正なFTPサーバのIPアドレスを、ローカルに立てた偽の検証用FTPサーバへ変更して実施しています。)

なお、Ryuk Stealerは盗んだファイルをアップロードする際、元のファイル名の先頭にランダムな数字を追加したファイル名に変更してアップロードします。これは同一ファイルを上書きアップロードしないようにした対策であると考えられます。

図22 実際にファイルの内容が検索されFTPサーバへアップローされる様子

■ランサムウェア「Ryuk」との関連性を示す挙動

なおRyuk Stealerはファイル名やフォルダ名に以下に挙げる文字列を含む場合は該当ファイルを窃取しません。ここで注目したいのは、これらの除外リストの一部はランサムウェア「Ryuk」が持つ除外リストと一致するということです。
特に分かりやすいところとして、Ryukが作成する脅迫文のファイル名となる「RyukReadMe.txt」やRyukにより暗号化されたファイルに追加される拡張子「.RYK」が含まれていることがわかります。

図23 Ryuk Stealerの除外リスト(収集しないファイル)

少し脱線しますが、ここであらためて考えてみると、ランサムウェアRyukが暗号化した後にRyuk Stealerに感染させても、重要なファイルはすでに暗号化されているため感染させる意味がありません。しかし、この除外リストを見る限り、攻撃者はRyuk Stealerが感染する端末に「.RYK」というファイルが含まれる可能性を配慮しています。つまり、Ryuk StealerはランサムウェアRyukによってすでに暗号化された後の端末で実行されることも意識して開発されているように見えます。このことから、一台一台攻撃者が手動で作業進捗を把握しながらRyuk Stealerをツールのように使用するというよりは、Active Directory等の仕組みを用い複数端末へある程度自動化された展開方法(RyukとRyuk Stealerの感染が端末によっては前後してしまうようなシチュエーション)で感染させる事を想定しているなどの背景があるのかもしれません。(または、単純に誤ってRyuk感染端末上で実行してしまった場合の除外対策である可能性もあるでしょう。)
いずれにしろ、RyukとRyuk Stealerの間には何らかの関連性があると考えられる理由の一つがここにあります。

話を戻しますが、上に挙げた除外リストが示すように、Ryuk Stealerには盗み出すファイルと盗まないファイルがあります。以下は実際の動作検証の様子ですが、例えば、画像ファイルはJPGの拡張子を持つものだけが対象であり、BMPやPNGなどは含まれません。また、拡張子がZIPである場合はファイルの構造をチェックし、中身がZIPファイルとして展開できるものだけを選定します(最新Ryuk Stealerはこの際にlibzipの外部モジュールは使用しません)。
なお、ファイルの中身のチェックが優先されるため、除外対象ファイルであっても(拡張子がRYKであったり、ファイル名がRyukReadMe.txtであったりしても)、ファイルの内容に特定の文字列を含んでいる場合はFTPサーバへアップロードされます。

図24 窃取されるファイルとされないファイル

さらにRyuk Stealerは、ファイルの内容に「000-00-0000」(数字9桁、123-45-6789等)の形式の文字列を含むファイルを発見した場合、該当ファイルも収集対象とします。この形式は米国の社会保障番号のフォーマットと同じであり、このフォーマットの文字列を含むファイルは個人情報を含む重要ファイルであることを示唆していることから、攻撃者の狙いが推測できます。

図25 特定フォーマットで構成された数字を含むファイルも収集

■ネットワーク上の別端末内のファイルも収集対象

Ryuk Stealerが窃取するファイルは、感染した端末のローカル上のものだけではありません。感染端末からGetIpNetTableで取得したArpテーブルの情報をもとにネットワーク上の別端末内のファイルも収集対象にします。その際、ネットワーク上の別端末にアルファベット順のドライブ名を一つずつ用いて管理共有へアクセスを試みます(管理共有について詳しくは前回の記事の後半をご覧ください)。

図26 ネットワーク上の別端末も収集対象

■補足情報:呼び出されないウインドウリソース

動作解説は以上となりますが、補足情報として、最新Ryuk Stealerのアンパック前のバイナリのリソースセクションには、一度も使用されないウインドウ(Form)がいくつか埋め込まれています。これらのウインドウは上記で解説した不可視ウインドウを使用したコールバック関数の仕組みとは一切関係なく、どこからも呼び出されないため、これらのウインドウの生成自体が行われていません。埋め込まれたウインドウリソースには、ZPAQ(オープンソースアーカイバ)のパスワード入力ウインドウや、何らかを追加/除去する中国語のウインドウ、色の選択に関わるスペイン語のウインドウがあり、それぞれに何の脈略もなく統一感もありません。
Ryuk Stealerのアンパック後のバイナリにはこれらのリソースデータが存在しないことからも、パッカー(暗号化ツール)による解析/検知妨害用のカモフラージュの可能性が高いと考えられます。
情報窃取系マルウェアにおける一般的な話として、ウインドウリソースを持つものはあまり多くはありません。それを鑑みた場合、こうしたウインドウリソースをバイナリに埋め込むことで、ファイルの構造上はウインドウを保有しているように見え、APIの呼び出しの観点も(実際にはこれらのウインドウとの繋がりは無いものの)、CreateWindowExやShowWindowなどウインドウ作成/表示に関わるAPIが確かに呼び出されており、機械的にまたは単純に表層判断した場合、一般アプリケーションであるかのように誤判断させることは可能です。つまり、そうした点で解析側を混乱させる解析妨害にもなり得ます。
解析妨害の側面以外にも例えば、ウイルス検知ソフトの中には一般アプリケーションへの誤検知を抑える観点からこうしたウインドウ関連の特徴をマルウェア検知における閾値の一つの算出基準にしている可能性も想定でき、こうしたカモフラージュにより検知の閾値への到達を下げられるというメリットもあるかもしれません。

図27 リソースセクションに埋め込まれた使用されないウインドウ(Form)

■まとめ

冒頭に述べた通り、ランサムウェア「Ryuk」が使用されたこれまでの攻撃でRyuk Stealerが実際に使用されたことを示す明確な証拠は現時点で確認されていませんが、RyukとRyuk Stealerの間に非常に近しい関連性があることもまた事実です。今回の解析で示したようにRyuk Stealerには攻撃連鎖の証拠隠滅に使用できる機能(第一引数のファイル削除)も保有している上に、一般的にランサムウェアの被害を受けた端末においては、あらゆるログを含めた証拠が暗号化されてしまう点やフォレンジック妨害などが施される場合がある点からも、通常のマルウェア感染のように明白な痕跡を調査するにはハードルが高い環境でもあるため、明確な証拠を見つけ出す事は容易ではないでしょう。
どちらにしても、MegaCortexV4などのように暗号化に対する脅迫に併せてファイルの流出を匂わせる脅迫も行ってくるランサムウェアがいくらか確認されており、今回ご紹介したRyuk Stealerのように流出を実際に行う関連マルウェアが現実に確認されていることからも、ランサムウェアの被害とファイルの流出という2点は無視できない連鎖脅威となってきていることを意識しておく必要性がありそうです。


Hash:
4DF7A3EE6A0B2EC32CED6C46A6EB555183E40BE6
E776FC6CCFA3DBC4904D06708734ED26A0BEC50D
3F427E029E1A9A849DA4AFE0F7756970F6CCE7B0