Android向け不正アプリ「Geost(ゲオスト)」は、ロシアのモバイルバンキングを標的とするバンキングトロジャンの活動を行うものです。Geostのボットネットによる被害者は、Virus Bulletinで調査報告が公開された昨年2019年の時点で、80万人を超えていました。調査によって、Geostがユーザから収集する情報や、利用する手法、そしてボットマスターとボットネット間で行われる通信など、ボットネットの背後にあるグループの活動について明らかにされています。
Geost(トレンドマイクロでは「Android OS_Fobus.AXM」として検出対応)は、チェコのセキュリティ研究所「Stratosphere Laboratory」のリサーチャーによって初めて明らかにされました。彼らは、別のマルウェアである「HtBot」の不正なプロキシネットワークを監視している時にこのマルウェアを検出しました。この興味深い発見を受け、トレンドマイクロではGeostのサンプルを解析し、さらなる詳細を調査することにしました。Geostには、何層もの難読化、暗号化、リフレクション、ジャンクコードのインジェクションが加えられており、リバースエンジニアリングによる解析を困難にしていました。コードを調査しアルゴリズムを分析するためにはまず、文字列を解読するためのPythonスクリプトを作成する必要がありました。
■初期解析
Geostは、ランダムに生成されたホスト名を持つ非正規のWebサイトで配布される、不正なアプリに隠れています。ユーザは通常、Google Playに見つからないアプリを探すか、あるいは正規アプリストアにアクセスできない時に、このアプリを発見します。それから正体不明のWebサーバ上でそのアプリのダウンロードリンクを見つけ、アプリをダウンロードしてスマートフォンで起動します。アプリは、アクセス許可をユーザに要求し、許可されるとマルウェア感染に成功します。
トレンドマイクロが解析したGeostのサンプルは、「установка」という名前(ロシア語で「設定」の意味)の不正アプリに隠れていました。このアプリは、インストール時には自身のアイコンとしてGoogle Playに類似したロゴを表示しますが、起動後はスマートフォンの画面上には表示されません。
アプリは起動すると、デバイス管理者権限を要求します。管理者権限は、基本的にデバイスに対するすべての権限をアプリに付与することを意味します。このような強力な権限を要求する正規アプリは限られており、不審な要求と言えます。
ユーザが気づかずに許可してしまう可能性のあるこの権限には、銀行アプリからの確認メッセージなど、SMSメッセージにアクセスするための権限が含まれます。これらのメッセージから、マルウェアはユーザの名前、口座残高、その他銀行口座の詳細を収集します。攻撃者は数回クリックするだけで、そうとは気づかないユーザの銀行口座からお金を移動することが可能になります。
必要な権限が許可されると、アプリの表示部分は閉じてアプリのアイコンを消し、アプリが削除されたとユーザに思わせます。解析に利用したデバイスには悪意のあるアクティビティについての警告は表示されませんでしたが、マルウェアはバックグラウンドで動作しており、デバイスのアクセス権限を獲得した攻撃者は、銀行アプリからのSMS確認メッセージなど送受信メッセージを監視することが可能になりました。
マルウェアは再起動後も活動の持続性を維持するために、BOOT_COMPLETEDおよびQUICKBOOT_POWERONブロードキャストに登録します。
■ステージ1
多くのマルウェアと同様にGeostの実行時間は複数のステージに分かれています。最初のステージ1部分はシンプルですが、より複雑なステージ2部分をダウンロードして復号し、実行します。
解析したGeostサンプルのAPKには、classes.dexファイルにコンパイル済みのJavaコードが格納されていました。また、AndroidManifest.xmlとリソースファイルも含まれていましたが、これらは、APKファイルの通常のコンテンツです。また、サイズが125kの「.cache」ファイルもありました。
解凍したclasses.dexファイルを逆コンパイルするためにdex2jar、jadx、jd-core/jd-gui、GhidraのすべてのJavaデコンパイラが使用されました。単一のデコンパイラではすべてのSmaliコードを逆コンパイルすることは不可能でした。
逆コンパイルされたコードは、一見、一連の文字列に部分的にエンコードされているようでした。しかし、文字頻度分析の結果からは、ランダムな文字の使用であることが示されました。
さらに、マルウェアには、実行速度を低下させるという以外はアプリの動作に影響を及ぼさない、余分なコードが含まれていることが明らかになりました。この余分なコードのせいで、マルウェアの有用な機能を持つコードが分割されており、実行パスが頻繁に変更されていたため、リバースエンジニアリングがさらに難しくされていました。どの分岐が行われたかは大抵、不明な値を持つ変数次第でした。同じことが「switch」、「if」、および「try/catch」コマンドブロックにも適用されていました。意味のないコードを持つ関数が挿入されているため、マルウェアの挙動全体が理解しにくくなっていました。
ジャンクコードのセグメントが徐々に取り除かれると、最初に使用された復号アルゴリズムが特定できました。ステージ1部分のすべての文字列はRC4で暗号化されていましたが、そうとわからないように、いくつかの機能に分割されたアルゴリズムが使用されていました。この後、必要な作業はRC4復号鍵を見つけることでした。
RC4は、復号された記号ごとに内部状態が変化するストリーム暗号です。複数の暗号化された文字列を復号するには、通常、暗号化されたときと全く同じ順序で復号を実行する必要があります。運よく、これは解析サンプルの場合には問題になりませんでした。サンプルのコード作成者は、復号と復号の間に内部状態を維持することなくRC4を単純化しており、RC4暗号化コードは常に状態配列S []をコピーしていました。
その後、共通コードライブラリの検索を開始しました。Android.support.v4ライブラリとReflectASM Java Reflectionライブラリが確認されました。
この時点で、ステージ1のコードが理解可能になりました。リフレクションコードを使用し、興味深いクラスやメソッドがうまく隠蔽されています。基本的に、ステージ1は同じRC4アルゴリズムと鍵を使用してステージ2のファイルを復号しました。
前述の「.cache」ファイルの名前は「.localsinfotimestamp1494987116」に変更され、復号後に「ydxwlab.jar」として保存され、そこから「.dex」ファイルがロードおよび起動されます。
コード作成者は、偽フラグである「HttpURLConnection」と接続先URLを挿入していました。コマンド&コントロール(C&C)サーバに接続するように見せかけていますが、このHTTP接続は決して実行されません。
ステージ1は、リサーチャーが「MaliciousClass」と命名したクラスを、ステージ2からロードします。
■ステージ2
「classes.dex」を解析すると、ステージ2も難読化と暗号化が施されていることが明らかです。しかし、今度は、記号名がステージ1の6〜12文字の文字列ではなく、1、2文字の文字列に部分的に置き換えられていました。また、文字列暗号化アルゴリズムが変更されており、ステージ1で使用されたアルゴリズムとは異なっていました。また、異なるツールが使用されていました。さらに、復号アルゴリズムのパラメータは、クラスごとに個別に変更されていました。
gotoコマンドがifブロックにジャンプするため、前回使用したJavaデコンパイラは復号アルゴリズムを逆コンパイルできませんでしたが、Jebデコンパイラのみがこの構造をうまく処理することができました。
各クラスの復号メソッドには異なるパラメータ順序と異なる定数が含まれていたため、Python復号スクリプトの記述はより困難になりました。つまり、復号スクリプトは、Smaliコードからアルゴリズムの設定を検出しそれ自体を適応させるか、各クラスの復号の前にスクリプト内でパラメータを手動で設定する必要があります。
文字列の解読後、使用されているライブラリ(以下を含む)が検出されます。
- AES暗号化エンジン
- Base64エンコード
- エミュレータ検出器
- ファイルダウンロードサービス
- IExtendedNetworkService
- USSD APIライブラリ
- Zip4jUtil
■初期化フェーズ
ステージ1から呼び出された前述の「MaliciousClass」は、リサーチャーが「Context」と名付けた、インスタンス化したクラスのエンベロープとして機能します。
ContextクラスはまずEmulatorDetectorサービスを起動します。その後、AdminServiceとLPServiceの2つのサービスを開始し、その後にメインアプリケーションのIntentを開始します。
- エミュレータ検出器
エミュレータ検出器は、エミュレートされた環境で実行されている兆候についてチェックします。解析サンプルは、Nox、Andy、Geny、Bluestacks、Qemu Androidの各エミュレータの存在を検出しました。
- AdminService
このサービスは、アプリケーションに管理者権限を付与することができます。機密データへのアクセスを可能にし、特権アクションの起動を可能にするため、クリティカルな部分です。
- LPService
このサービスは、アプリケーションの実行とC&Cサーバへの接続を維持する役割を果たします。WakeLockおよびWifiLock acquire()呼び出しを使用して、この状態に到達しました。このサービスの副作用は、バッテリーの消耗が大きいことですが、ほとんどのユーザは通常この現象を無視します。
次に、LPServiceはLPServiceRunnable スレッドを作成します。このスレッドは5秒ごとに起動し、以下のサービスの監視と再起動を担当します。
- MainService
- AdminService
- SmsKitkatService
このサービスはまた、実行中のプロセスとタスクに関する情報を収集します。さらに、定期的にWebViewActivityを起動し、ブラウザウィンドウを開いて任意のURLにアクセスしたり、不正なコードを起動したりします。なお、解析したサンプルでは、WebViewActivityコードは実装されていませんでした。
- MainService
MainServiceは、まず、時間スケジューリングタスクのためにAlarmManagerをフックし、次に2つのブロードキャストレシーバー「MainServiceReceiver1」と「MainServiceReceiver2」を登録します。初期化フェーズの最後に、MainServiceRunnableスレッドを起動します。オーバーロードされたonDestroy()メソッドが実行されると、MainServiceが再び起動されます。
MainServiceの重要なメソッドはprocessApiResponse()で、これは、C&Cサーバから受信したJSON文字列形式のコマンドを処理します。
- ClearService
このサービスはClearServiceRunnableスレッドを呼び出します。このスレッドは、コマンドのロックおよびロック解除(ユーザアクティビティのブロックおよびブロック解除)を担当するため、ボットネットを操作する攻撃者はユーザの介入なしにリモートタスクを実行できます。また、ClearServiceは、終了させても再起動します。
- SmsKitkatService
このサービスは、標準のSMSメッセージングアプリケーションを、攻撃者が作成した別のアプリケーションに置き換えるために準備されています。解析サンプルのバージョンでは、デフォルトのものを使用していました。
■コマンド
解析したサンプルが認識したコマンドのリストは、以下の表とスクリーンショットで表すことができます(コードで定義された順序で記載)。
コマンド | 内容 |
#conversations | content://sms/conversations/、content://sms/inbox、およびcontent://sms/sent内のすべてのSMSメッセージから連絡先、本文、日付、タイプの列を収集し、C&Cサーバに送信する |
#contacts | content://com.android.contacts/data/phonesからすべての連絡先のリストを収集し、C&Cサーバに送信する |
#calls | content://call_log/callsから実行されたすべての通話ログを収集し、C&Cサーバに送信する |
#apps | インストールされているパッケージ名とラベルのリストを収集し、C&Cサーバに送信する |
#bhist | (このコマンドは解析サンプルでは無視される) |
#interval {set:number} | C&Cサーバコマンドを取得する期間を設定する |
#intercept | SMSを傍受する電話番号を設定する(「すべて」または番号のリスト) |
#send id:, to:, body: | SMSを送信する |
#ussd {to:address, tel:number} | USSDフレームワーク経由で通話する |
#send_contacts | 電話帳のすべての連絡先にSMSを送信する |
#server | 実行する予定時刻を設定する |
#check_apps {path:uri_to_server} | 実行中のアプリのリストをC&Cサーバに送信し、パラメータで定義されたパスからarchive.zipファイルをerror.zipとしてダウンロードし、解凍する。 Zipアーカイブのパスワードは「encryptedz1p」、デフォルトのサーバ名はhxxp://fwg23tt23qwef.ru/ |
#send_mass {messages: {to:address, body:text}, delay:ms} | 複数のSMSメッセージを異なるアドレスに、送信の間に間隔を空けて送信する |
#lock | ClearServiceRunnableからRLAサービスを開始する。これは、AKEYCODE_HOME、AKEYCODE_CAMERA、およびAKEYCODE_FOCUSのkeyPressイベントを傍受する。また、onBackPressed()アクティビティメソッドを傍受し、呼び出し音をミュートし、すべてのSMS通知をクリアし、自身を停止し、電話を応答不能にする |
#unlock | #lockコマンド下にリストされたアクションを無効にし、ClearServiceRunnableを停止して電話のロックを解除する |
#makecall {number:tel_number} | 標準のandroid.intent.action.CALL APIを使用して通話発信する |
#openurl {filesDir=j:url} | WebページのURLを開く |
#hooksms {number:tel_number} | ある番号へフックする。すべての着信SMSメッセージをパラメータ内の数値に転送する |
#selfdelete | タスク時間を解析不能な文字列値に設定し、自己スケジューリングタスクを停止する |
■ApiRequest、ApiResponse、ApiInterfaceImpl
ApiRequest、ApiResponse、およびApiInterfaceImplクラスは、C&Cサーバとの通信を可能にします。接続パラメータの初期化で、replaceReqWithRandomStr変数の値はデフォルトでtrueに設定され、コード内では変更されません。
C&CサーバURLのランダムな文字列を生成するために、アルゴリズムが使用されていました。その後、API接続が初期化され、C&Cサーバのホスト名が設定されます。
C&CサーバのAPI使用は、C&Cサーバのコマンド「#contacts」の実装から判断できます。最後に、コマンドのパラメータがJSON形式として追加され、文字列に変換されます。
このように、Geostには何層もの難読化、暗号化、リフレクション、ジャンクコードのインジェクションなどの解析困難化手法が加えられていました。サイバー犯罪者は目的達成のために様々な巧妙な手法を編み出します。有効な対策の実施には、このような困難化手法を明らかにしていくことも重要です。
■被害に遭わないためには
トレンドマイクロは、「2020年セキュリティ脅威予測」の中で、オンラインバンキングおよび決済システムをターゲットとする「Geost」のような不正アプリファミリの継続的な拡散を予測しました。モバイルユーザはベストプラクティスに従い、危険が潜むモバイル環境を安全に航行できるよう、デバイスを保護する必要があります。そのような対策の第一歩は、Androidの公式アプリストア以外からアプリをダウンロードしないようにすることです。
しかし残念ながら、攻撃者は正規のアプリストアにおいても不正なアプリを配布する手段を見つけています。発見された不正アプリを削除し続ける正規ストア側の活動も重要ですが、ユーザは、アプリをダウンロードする前にレビューその他の情報を慎重に調べることで、不正アプリを回避することができます。
ユーザは、インストールの際にアプリが要求してくる権限を許可する前に精査する必要があります。インストール後には、感染の兆候の可能性があるパフォーマンスの低下やバッテリー寿命の低下など、デバイスの変化に注意する必要があります。そのような場合、新しくインストールしたアプリをすぐに削除してください。また、定期的にデバイスをチェックして、使用していないアプリを削除することができます。
■トレンドマイクロの対策
トレンドマイクロでは、モバイル環境での総合セキュリティ対策として、個人利用者向けにはGoogle Playで利用可能な「ウイルスバスター モバイル」、法人利用者向けには「Trend Micro Mobile Security™」を提供しています。これらの製品ではトレンドマイクロのクラウド型セキュリティ基盤「Trend Micro Smart Protection Network(SPN)」の機能である「Mobile App Reputation(MAR)」技術や「Web レピュテーション(WRS)」技術により、不正/迷惑アプリの検出や不正/迷惑アプリに関連する不正 Web サイトのブロックに対応しています。
■侵入の痕跡(Indicators of Compromise、IoC)
侵入の痕跡(Indicators of Compromise、IoCs)はこちらを参照してください。
参考記事:
- 「 Dissecting Geost: Exposing the Anatomy of the Android Trojan Targeting Russian Banks」
by Vit Sembera (Threats Analyst)
翻訳: 室賀 美和(Core Technology Marketing, Trend Micro™ Research)