2012/03/06

UpdateされたApperhand(AKA Counterclank)を解析してみた

ご無沙汰しております。
本業が年度末作業で多忙を極めておりまして、Blogはおろか調査すらままならぬ今日この頃です。
さて、機を逸した感はありますが、今回は以前のエントリで前振りしていたApperhandについて書こうと思います。
今さらながら Apperhand についてエントリを書くのにはいくつか理由があります。

  1. Malware 対策ベンダ間でMalwareの定義に対する議論を起こすきっかけとなった
  2. 私が昨年から Ad モジュールの問題で追跡していた超光懐中電灯無料アプリに組み込まれていた
  3. Trojan として Symantec に公開された後にもバージョンアップが行われている事を確認した
  4. 暗号化/難読化が話題に上がっている(私も関心を持っている)最中に Apperhand が難読化をかけていた

2~4については全くの偶然によるものなのですが、ここまで絡まれると因縁めいたものを感じざるを得ません。
ここまで引きずるつもりもなかったのですが、これで超光懐中電灯無料アプリとの付き合いに終止符を打とうと思います。


さて、Apperhand の話は 2 月初めまでさかのぼります。念のため当時の関連するエントリをまとめておきます。

  • マルウェア(とある技術屋の日記: 2/1) SymantecがTonclank(AKA Plangton, Toplank)をベースにした広告モジュール Counterclank の情報を公開
  • マルウェア(とある技術屋の日記: 2/9) エントリ後半で超光懐中電灯からTrojan.AndroidOS.Plangton.a(AKA Counterclank)検出の記述
  • マルウェア(とある技術屋の日記: 2/22) McAfeeがToplankからAppHndに改名。超光懐中電灯がさらに VersionUp するとともに組み込まれているApperhandモジュールもVersion Up

1.対策ベンダ間による「Malware」の定義における議論

  • 1/27 Symantec が AndroidMarket で配信されているアプリケーションから Tonclank をベースして作成されたとみられる広告モジュール Apperhand を Malware/Counterclank として情報公開 (Android.Counterclank Found in Official Android Market)
  • 当日のうちに Lookout が速攻で Symantec の Malware 判定が FUD であると反論のエントリを自社 Blog に公開 (Lookout’s take on the ‘Apperhand’ SDK (aka ‘Android.Counterclank’) )
  • 1/30 そして、Symantec は Lookout の反論に対して自社のポリシーを主張。Malware をベースに作られていること、その機能がユーザにとって不要であることが明白で実際に不評が出ていることなどから、「ユーザがより確実な情報に基づいてインストールの可否を判断する為」とエントリでは述べています。 (An Update on Android.Counterclank)

そもそも、ベンダ各社で用語の定義や判断基準が異なる事に起因しているわけですが、Symantec の言う「ユーザがより確実な情報に基づいてインストールの可否を判断できること」というポリシーについては同意です。
一方で Lookout が Malware ではないという言い方をしたことについても、見方によって理解はできます。彼らにとって "Malware" というのが破壊的・攻撃的な(悪意をもった)意図がその機能にあるかどうか、つまりより狭義の意味で Malware という言葉を使うべきだという主張と考えられます。ただし、ユーザの視点から見ると、"Apperhand がアグレッシブな広告である" という表現は消極的すぎると感じられます。

残念ながら両者の議論はここで止まってしまいました。私としてはこれをきっかけに他のベンダを巻き込んで用語に対する定義統一の方向に向いてくれる事を望んでいます。


2.超光懐中電灯無料アプリがMalware対策ソフトのスキャンに引っかかる

Symantec が Counterclank の情報公開してほどなく Twitter で偶然にも超光懐中電灯無料アプリで Malware を検知したという Tweet を見かけ、ご本人にどの対策ソフトで何が引っかかったのか確認しました。

Malware の種類はわからなかったものの、カスペルスキーで引っかかったとの事で早速カスペルスキーをダウンロードしスキャンをしてみました。 すると、偶然にもカスペルスキーが検知したのは Plangton つまり Apphand かその前身となったモジュールと言う事が判明しました。


fl193

そこで詳細を調べるべく apk を解析する事にしました。
まずは Malware として検知されたコードの特定です。
Plangton と言うことは独立したモジュールとして存在しているはずなので、まずは classes.dex のファイル構成を確認します。

#pwd
/Android/tmp/light 1.9.3/out/com
#ls -l
total 0
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 adserver
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 adwhirl
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 amobee
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 apperhand
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 flurry
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 google
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 inmobi
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 jumptap
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 mdotm
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 millennialmedia
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 mobclix
drwxr-xr-x+ 1 users None 0 Feb  8 17:55 zestadz

ありました、Apperhand です。
これで Plangton の正体は Android.Counterclank (または亜種)である可能性がかなり高くなりました。
次に、Symantec のサイトで公開されている Malware の特徴と照合して Counterclank か否かを確認します。


a.C&C サーバへのアクセス

Counterclank は C&C サーバ(http://[Censored].com/ProtocolGW/protocol)に問い合わせをしてコマンドを取得します。 これは /com/apperhand/device/android/AndroidSDKProvider.smali にありました。

.line 148
const-string v0, "M_SERVER_URL"

const-string v1, "http://[Censored].com/ProtocolGW/protocol"
invoke-virtual {v2, v0, v1}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

b.Apperhand の機能

Symantec のサイトでは Apperhand は以下の機能を持っているとしています

  • デバイス上のブックマークをコピーする
  • オプトアウトの詳細をコピーする
  • プッシュ通知をコピーする
  • ショートカットをコピーする
  • 最後に実行されたコマンドを識別する
  • ブラウザのホームページを変更する
  • ビルド情報を盗み取る
Android.Counterclank(Symantec)

これらの機能は、/com/apperhand/common/dto 配下にありました。

#pwd
/Android/tmp/light 1.9.3/out/com/apperhand/common/dto
#ls -l
total 168
-rwxr-xr-x  1 users None  4587 Feb  8 17:55 Activation.smali
-rwxr-xr-x  1 users None 11389 Feb  8 17:55 ApplicationDetails.smali
-rwxr-xr-x  1 users None  3642 Feb  8 17:55 AssetInformation$State.smali
-rwxr-xr-x  1 users None  5829 Feb  8 17:55 AssetInformation.smali
-rwxr-xr-x  1 users None  8849 Feb  8 17:55 BaseBrowserItem.smali
-rwxr-xr-x  1 users None  1124 Feb  8 17:55 BaseDTO.smali
-rwxr-xr-x  1 users None  2820 Feb  8 17:55 Bookmark.smali
-rwxr-xr-x  1 users None  7326 Feb  8 17:55 Build.smali
-rwxr-xr-x  1 users None 12978 Feb  8 17:55 Command$Commands.smali
-rwxr-xr-x  1 users None   971 Feb  8 17:55 Command$ParameterNames.smali
-rwxr-xr-x  1 users None  9212 Feb  8 17:55 Command.smali
-rwxr-xr-x  1 users None  6071 Feb  8 17:55 CommandInformation.smali
-rwxr-xr-x  1 users None  6952 Feb  8 17:55 CommandStatus$Status.smali
-rwxr-xr-x  1 users None  5065 Feb  8 17:55 CommandStatus.smali
-rwxr-xr-x  1 users None  7713 Feb  8 17:55 DisplayMetrics.smali
-rwxr-xr-x  1 users None  2186 Feb  8 17:55 Homepage.smali
-rwxr-xr-x  1 users None  8785 Feb  8 17:55 NotificationDTO.smali
-rwxr-xr-x  1 users None  3820 Feb  8 17:55 OptOutDetails.smali
-rwxr-xr-x  1 users None 12038 Feb  8 17:55 Shortcut.smali
-rwxr-xr-x  1 users None  4031 Feb  8 17:55 Status.smali
drwxr-xr-x+ 1 users None     0 Feb  8 17:55 protocol

前述の機能と照らし合わせると以下の通りとなります。

  • デバイス上のブックマークをコピーする - Bookmark.smali
  • オプトアウトの詳細をコピーする - OptOutDetails.smali
  • プッシュ通知をコピーする - NotificationDTO.smali
  • ショートカットをコピーする - Shortcut.smali
  • 最後に実行されたコマンドを識別する - CommandStatus.smali
  • ブラウザのホームページを変更する - BaseBrowserItem.smali
  • ビルド情報を盗み取る - Build.smali

実際のコードの確認については長くなるので省略しますが、これで超光懐中電灯無料アプリに Counterclank が組み込まれている事が明らかになりました。
超光懐中電灯無料アプリは、私が昨年からずっとその動向を見てきただけに、当時かなり衝撃を受けました。今までは端末情報を抜き出す広告モジュールの問題を取り上げてきたものがここで Malware 対策ベンダによって Trojan として完全に Malware 認定されてしまったわけです。


3.それでも配布は止まらない - Apperhand のアップデート

それからしばらくして超光懐中電灯無料アプリがバージョンアップされてことに気付き、Market から入手してみてみました。
この当時、徳丸先生が Twitter や Blog 等で Android アプリにおける暗号化や難読化を話題にされており、私も関心をもって見ていました。
ここでも偶然に Apperhand とこの話題が結びつく変更が行われていました。
Market 上の超光懐中電灯無料アプリの変更点は、特定の端末のLEDライトが点灯するよう対応したというものだったのですが、実際にはApperhand モジュールも変更されていました。
Apperhand は、モジュールとして配布されているのでおそらく配布元がバージョンアップしたものを取り込んだのではないかと推測しています。


変更点を確認すべく Apperhand モジュールの解析を始めようと diff(テキストファイルの差分を表示するコマンド)で確認したところところどころに差分があることがわかりました。 diff の結果はエントリに収まりきらないくらいの量なので割愛しますが、機能的にはほとんど変更点はなく、ロジックの多少の変更と難読化処理がかけられている事が原因でした。

前回のコードと比較すると文字列が暗号化されていることがわかります。
以下に該当のコードを記載します。


Ver1.9.3の AndroidSDKProvider Class の一部

.line 146
const-string v3, "APPLICATION_ID"

invoke-virtual {v2, v3, v1}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
.line 147 const-string v1, "DEVELOPER_ID"
invoke-virtual {v2, v1, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
.line 148 const-string v0, "M_SERVER_URL"
const-string v1, "http://[Censored].com/ProtocolGW/protocol"
invoke-virtual {v2, v0, v1}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

Ver1.9.5の AndroidSDKProvider Class の一部(1.9.3と同じ処理をしている箇所)

.line 155
const-string v3, "CRoQAlVGS1keGVoEHgRLEBoOGRdLEUE+agQtJzsiJj8tABJOHhYdGwYHQQU="

invoke-static {v3, v5}, Lcom/apperhand/device/a/d/a;->a(Ljava/lang/String;I)[B
move-result-object v3
.line 158 new-instance v4, Ljava/lang/String;
invoke-static {v3, v6}, Lcom/apperhand/device/a/d/b;->a([B[B)[B
move-result-object v3
invoke-direct {v4, v3}, Ljava/lang/String;->([B)V
.line 163 const-string v3, "APPLICATION_ID"
invoke-virtual {v2, v3, v1}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
.line 164 const-string v1, "DEVELOPER_ID"
invoke-virtual {v2, v1, v0}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
.line 165 const-string v0, "M_SERVER_URL"
invoke-virtual {v2, v0, v4}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

上記は AndroidSDKProvider Class の中で Intent をする際に付加するパラメータ(putExtra)の設定している部分です。
注目するところは ver1.9.5 の line155, 158, 165 の処理です。ver1.9.3 では "M_SERVER_URL" というキーで"http://[Censored].com/ProtocolGW/protocol"という C&C サーバの URLをIntentの際に渡しているのですが、ver1.9.5ではこの処理が複雑になっています。

まず、"APPLICATION_ID"の前に暗号化されたStringがあります。これは暗号化されたC&CサーバのURLです。これをその下にある Lcom/apperhand/device/a/d/a;->a(Ljava/lang/String;I)[B で下処理したバイナリに変換し、line158で復号したバイナリ文字列をStringに置き換えています。
復号された文字列はv4というレジストリに保持され、後のline165で"M_SERVER_URL"というキーといっしょにIntent時に渡されます。つまり、このClassの外から見るとこの暗号化には意味がありません。
つまり、ここでは難読化の目的で文字列が暗号化されているということになります。
難読化をかけること自体に問題はありませんが、C&Cサーバへのアクセス機能含め、問題のロジックをそのままに難読化をかけてくる辺り悪意を感じます。


念のため、ApperhandがいまだにC&Cサーバとやりとりを行っているか確認するためにLogを確認してみました。

03-01 12:39:53.296 E/b ( 5645): Unexpected error!!!
03-01 12:39:53.296 E/b ( 5645): com.apperhand.device.a.d.f: Status code is 503, address = [http://[Censored].com/ProtocolGW/protocol/commands],Headers = [[Lorg.apache.http.Header;@40580fc8],statusLine = [HTTP/1.1 503 Service Unavailable]
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.c.c.a(NetworkUtils.java:142)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.b.b.a(TransportHttpApache.java:94)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.a.b.a(SDKManager.java:52)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.AndroidSDKProvider$1.a(AndroidSDKProvider.java:229)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.AndroidSDKProvider.onHandleIntent(AndroidSDKProvider.java:316)
03-01 12:39:53.296 E/b ( 5645):   at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
03-01 12:39:53.296 E/b ( 5645):   at android.os.Handler.dispatchMessage(Handler.java:99)
03-01 12:39:53.296 E/b ( 5645):   at android.os.Looper.loop(Looper.java:143)
03-01 12:39:53.296 E/b ( 5645):   at android.os.HandlerThread.run(HandlerThread.java:60)
03-01 12:39:53.296 E/b ( 5645): Exception!!!
03-01 12:39:53.296 E/b ( 5645): com.apperhand.device.a.d.f: Status code is 503, address = [http://[Censored].com/ProtocolGW/protocol/commands],Headers = [[Lorg.apache.http.Header;@40580fc8],statusLine = [HTTP/1.1 503 Service Unavailable]
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.c.c.a(NetworkUtils.java:142)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.b.b.a(TransportHttpApache.java:94)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.a.b.a(SDKManager.java:52)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.AndroidSDKProvider$1.a(AndroidSDKProvider.java:229)
03-01 12:39:53.296 E/b ( 5645):   at com.apperhand.device.android.AndroidSDKProvider.onHandleIntent(AndroidSDKProvider.java:316)
03-01 12:39:53.296 E/b ( 5645):   at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
03-01 12:39:53.296 E/b ( 5645):   at android.os.Handler.dispatchMessage(Handler.java:99)
03-01 12:39:53.296 E/b ( 5645):   at android.os.Looper.loop(Looper.java:143)
03-01 12:39:53.296 E/b ( 5645):   at android.os.HandlerThread.run(HandlerThread.java:60)
03-01 12:39:53.296 D/b ( 5645): After executing commands
03-01 12:39:53.306 D/b ( 5645): Next command is on [60] seconds

どうやら、C&Cサーバは存在しているものの機能していない模様です。サーバから503が返されExceptionが発生しています。
ブラウザからもアクセスしてみましたが、やはり503が返ってきました。
503error
しかし、アプリは相変わらずC&Cサーバへアクセスしコマンドの取得を試みている事が分かります。


まとめ

  • 超光懐中電灯無料アプリは対策ベンダが認めるMalware(ベンダによってはPUP:利用することが望ましくないプログラム)になりました
  • Apperhandは、SymantecからTrojanとして認定された後も難読化していまでも配布しています
  • 一方、C&Cサーバ自体は現在のところ機能していませんが、サーバ自体は存在しておりいつまた利用されるかわかりません

結論としては、超光懐中電灯無料アプリはインストールすべきではないということです。
超光懐中電灯無料アプリについてはこれで終わりにしましょう。

※Apperhandの難読化に関してもう少しこのエントリで書こうと思いましたが、長くなりそうなのでまた別の機会にしようと思います。

0 件のコメント:

コメントを投稿