ラベル 超光懐中電灯 の投稿を表示しています。 すべての投稿を表示
ラベル 超光懐中電灯 の投稿を表示しています。 すべての投稿を表示

2012/05/18

超光懐中電灯からApperHandモジュールが取り除かれていました

はい、タイトルどおりなわけですが、1.9.6のUpdateからMalware対策ソフトによって検知される事はなくなりそうです。

ApperHand自体C&Cサーバが沈黙してたりしたので機能していないと見て外したのか、Malwareの指摘を受けて外したのか、いずれにしてもこれで多少リスクは軽減された事になります。
ただし、他の広告モジュールは以前入っていますので、広告モジュールの端末識別情報や位置情報送信によるリスクは変わりませんのでその点はご注意ください。

2012/04/06

改めて警告します。「超光懐中電灯無料アプリ」は利用することが望ましくないアプリです

マルウェア対策ソフトで検知されても、アプリが持っている危険性に対して信じようとしない(信じたくない)方がいらっしゃるようなので…。
超光懐中電灯無料アプリは、起動するたびに端末を特定する情報と共に現在の位置情報を広告企業に送っていますし、いまでも遠隔操作用の命令を送り込むサーバに接続を試みています。

それでもご自身の端末で使うことを厭わない方は、ご自身の責任でご使用ください。でも、「(リスクすら説明せずに無邪気に)他人に勧めるのはやめてください」。


以下、かなり大雑把ですが超光懐中電灯無料アプリの問題点をまとめておきます。

超光懐中電灯無料アプリにはApperHandと呼ばれる不適切なプログラムや端末の位置情報/識別情報を収集する広告プログラムが多数組み込まれています。

この組み込まれたプログラムによってアプリを立ち上げるたびに、次の動作をします。

  • 広告プログラムによって端末を特定できる情報と端末の位置情報を広告企業に送信します
  • ApperHandによって、ブックマークやブラウザのホームページの変更。端末のホーム画面上にショートカットアイコンを勝手に生成する場合があります
  • ApperHandによって、端末の詳細な情報(OSのバージョンや、端末の種類等)が収集されます
  • ApperHandが、インターネット上のサーバにアクセスして、そこからコマンド(命令)を受け取り、上記の動作を自動で行います

これによって、以下の脅威にさらされる可能性があります

  • 端末が特定できる識別情報と端末の位置情報を取得することで、端末を持っている人を追跡する事が出来ます
  • 表示された広告をクリックすると、端末の識別情報とともにクリックした広告の内容を組み合わせて、端末の利用者の関心や趣味などのプライベートな情報を収集する場合があります
  • アプリを起動したときに情報を送信する為、そのアプリがいつ、どこで使われたか(利用履歴)を知ることができます。(位置情報と組み合わせれば、どの端末がいつも深夜○時に自宅で懐中電灯アプリを使ってるとか、そういう行動パターンを推測する事ができるようになります。)
  • ブックマークやブラウザのホームページを書き換えることで不正なサイトに誘導されたり、利用したいページを見れない状態になる場合があります
  • インターネット上のサーバからの命令によってリモート(遠隔)操作で情報の搾取や改ざんが行われる場合があります

懐中電灯の代わりに便利だからという理由で使う代償として上のリスクを受容できるかどうか考えてから使いましょう。


超光懐中電灯無料アプリに関する過去のエントリまとめ(技術的な話が多めです)

不適切なアプリとして(私を含め複数の人が)通報してるのだが…Googleさん本当に動く気ないのな…。

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の難読化に関してもう少しこのエントリで書こうと思いましたが、長くなりそうなのでまた別の機会にしようと思います。

2011/11/29

「超光懐中電灯」を解析してみた(続編)…まだ続きそう…

追記 2012/10/01

「超光懐中電灯」で調べて本Blogエントリにたどり着いた方へ

本エントリは、2011年11月時点のアプリケーションを解析した結果です。その後アプリケーションは幾度かのバージョンアップを経てApperHandという広告モジュールを導入した結果、いくつかのウィルス対策ベンダからPUP(利用することが望ましくないプログラム)としてスキャンソフトで検知されるようになっています。

本アプリについては、本Blogエントリ「改めて警告します。「超光懐中電灯無料アプリ」は利用することが望ましくないアプリです」を参照ください。


前編は後々まとめて公開します。
@ChihiroShiiji さんの「どうしてこうなった?不思議なパーミッションを要求するAndroidアプリ・カタログ」 をご覧ください。

(前回のまとめ)
「迷惑な広告無し」と謳いながらアプリの機能に不要と思われるPermissionが付与されている超光懐中電灯。
AndroidManifest.xmlを見ると10件もの広告モジュールが組み込まれている事がわかった。
さらにdexを解析すると、広告モジュールの多くが端末情報や位置情報を取得するメソッドを実行している事が判明する。
不可思議なパーミッションの問題は、プライバシー情報の漏えい問題へと発展するのか?!


というわけで、実際に広告モジュールが収集した情報が外部に送信されているか解析を進めてみました。
結論から申し上げますと超光懐中電灯の広告モジュールは黒です。しかもある広告モジュールの仕様はかなり危険です。スパイウェア認定していいくらいに。
なお、限られた時間でもくもくと書きながら解析をしているので、誤字脱字含め勘違い等あればご指摘ください。
結論だけが知りたい方は記事の最下部をご覧ください。。。


先日のTwieetにも書きましたが、広告モジュールが直接HttpRequestを送信しているケースもあり、MAISTのように端末のLogから送信内容を確認するのは困難です。
そこでアプリを実際に動かして通信をキャプチャし解析するか、コードを直接解析するかの2択になるのですが残念なことに前者は上手くいきませんでした。(多分私の環境の問題で広告モジュールが上手く動作しなかった)
そこで(いたしかたなく)コードを解析することに。(smaliのコードを読むのは初めてなので、金床さんのサイトを参考にさせていただきました。)

ここからは私の解析の流れをそのまま記録しておきます。
先に書いた通り、smaliのコードを読むのが初めて、というか静的解析自体がほぼ初めてなので後で何方かが再検証できるようにという目的です。

まず、この膨大な広告モジュールのどこから手をつけるかというところで、取得している情報から最もインパクトの大きいであろうJumpTapというモジュールに絞ります。
こやつは、LocationManagerと、TelephonyManagerから取得できるであろうあらゆる端末情報を収集している憎いやつです。

まず、前回の解析結果の続きから見てみます。
以下はLocatoinManagerのgrepの結果です。

./com/jumptap/adtag/utils/JtLocation$1.smali(66,91): invoke-static {}, Lcom/jumptap/adtag/utils/JtLocation;->access$100()Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation$1.smali(70,48): invoke-virtual {v0, p0}, Landroid/location/LocationManager;->removeUpdates(Landroid/location/LocationListener;)V
./com/jumptap/adtag/utils/JtLocation.smali(11,23): .field private static locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(32,59): sput-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(64,56): .method static synthetic access$100()Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(69,59): sget-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(128,59): sget-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(168,38): check-cast v0, Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(170,59): sput-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(173,59): sget-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(177,48): invoke-virtual {v0, v1}, Landroid/location/LocationManager;->getLastKnownLocation(Ljava/lang/String;)Landroid/location/Location;
./com/jumptap/adtag/utils/JtLocation.smali(193,59): sget-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;
./com/jumptap/adtag/utils/JtLocation.smali(203,56): invoke-virtual/range {v0 .. v5}, Landroid/location/LocationManager;->requestLocationUpdates(Ljava/lang/String;JFLandroid/location/LocationListener;)V

どうやらJtLocation.smaliでロケーションを取得しているようです。
とりあえずJtLocation.smaliを見てみるとありました。
.method private registerLocationListeners(Landroid/content/Context;)Vの中の56行目になります。

.line 56
sget-object v0, Lcom/jumptap/adtag/utils/JtLocation;->locationManager:Landroid/location/LocationManager;

const-string v1, "network"

invoke-virtual {v0, v1}, Landroid/location/LocationManager;->getLastKnownLocation(Ljava/lang/String;)Landroid/location/Location;

move-result-object v0

invoke-static {v0}, Lcom/jumptap/adtag/utils/JtLocation;->setCurrentLocation(Landroid/location/Location;)V

registerLocationListenersメソッドの中でandroid.location.LocationManager.getLastKnownLocationをCallし、その結果をsetCurrentLocationメソッドに投げています。
名前の通りsetCurrentLocationは現在地の情報を格納するためのsetアクセサです。
となるとgetアクセサもあるはず。

.method public static getCurrentLocation()Landroid/location/Location;
.registers 1

.prologue
.line 107
sget-object v0, Lcom/jumptap/adtag/utils/JtLocation;->currentLocation:Landroid/location/Location;

return-object v0
.end method

ありました。次にこのgetCurrentLocationが使われているメソッドを探してみましょう。
「getCurrentLocation」をgrepします。

./com/jumptap/adtag/utils/JtAdManager.smali(743,61): invoke-static {}, Lcom/jumptap/adtag/utils/JtLocation;->getCurrentLocation()Landroid/location/Location;
./com/jumptap/adtag/utils/JtLocation.smali(89,23): .method public static getCurrentLocation()Landroid/location/Location;

JtAdManager.smaliで使われています。
早速該当箇所を探してみます。

.method public static getLocation(Landroid/content/Context;)Ljava/lang/String;
.registers 6
.parameter "context"

.prologue
.line 95
invoke-static {p0}, Lcom/jumptap/adtag/utils/JtLocation;->init(Landroid/content/Context;)V

.line 96
const/4 v1, 0x0

.line 97
.local v1, retVal:Ljava/lang/String;
invoke-static {}, Lcom/jumptap/adtag/utils/JtLocation;->getCurrentLocation()Landroid/location/Location;

move-result-object v0

この後、位置情報はStringBuilderで「llatitude/longitude=xxx%2Cxxx」という形に形成されてCall元にReturnしていました。
さて、このメソッドをCallしてるのはどこでしょうか。「getLocation」でgrepした結果です。

./com/jumptap/adtag/callbacks\JtWebviewCb.smali(73,16): .method public getLocation(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
./com/jumptap/adtag/callbacks\JtWebviewCb.smali(90,36): const-string v3, "JtWebViewCB::getLocation options: "
./com/jumptap/adtag/utils/JtAdManager.smali(730,23): .method public static getLocation(Landroid/content/Context;)Ljava/lang/String;
./com/jumptap/adtag/utils/JtAdUrlBuilder.smali(191,64): invoke-static {v2}, Lcom/jumptap/adtag/utils/JtAdManager;->getLocation(Landroid/content/Context;)Ljava/lang/String;

最終行(4行目)に注目してください。「JtAdUrlBuilder.smali」つまり「JtAdUrlBuilder」クラスで利用されています。
クラス名から推測するとURLの生成クラスである可能性があります。核心に近づいてきました。
該当メソッドはかなり長いので該当部分だけ抜き出します。

.method public getAdUrl(Landroid/webkit/WebView;Ljava/lang/String;)Ljava/lang/String;


.line 40
iget-object v2, p0, Lcom/jumptap/adtag/utils/JtAdUrlBuilder;->context:Landroid/content/Context;

invoke-static {v2}, Lcom/jumptap/adtag/utils/JtAdManager;->getLocation(Landroid/content/Context;)Ljava/lang/String;

move-result-object v1

.line 41
.local v1, location:Ljava/lang/String;
if-eqz v1, :cond_9a

.line 42
const-string v2, "&ll="

invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

invoke-static {v1}, Lcom/jumptap/adtag/utils/JtAdUrlBuilder;->encodeParam(Ljava/lang/String;)Ljava/lang/String;

move-result-object v3

invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

今まで取得してきたパラメータをStringBuilderで次々に連結させているようです。
位置情報は"&ll="というパラメータ名と結合しエンコードしています。

ここで、端末情報が含まれるか合わせて確認しましょう。

.line 51
const-string v2, "&hid="

invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v2

iget-object v3, p0, Lcom/jumptap/adtag/utils/JtAdUrlBuilder;->context:Landroid/content/Context;

invoke-static {v3}, Lcom/jumptap/adtag/utils/JtAdManager;->getHID(Landroid/content/Context;)Ljava/lang/String;

move-result-object v3

invoke-static {v3}, Lcom/jumptap/adtag/utils/JtAdUrlBuilder;->encodeParam(Ljava/lang/String;)Ljava/lang/String;

move-result-object v3

invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

これのようですね。JtAdManager.smaliに該当のメソッドがありました。

.method public static getHID(Landroid/content/Context;)Ljava/lang/String;
.registers 3
.parameter "context"

.prologue
.line 79
invoke-static {p0}, Lcom/jumptap/adtag/utils/JtAdManager;->getTelephonyManager(Landroid/content/Context;)Landroid/telephony/TelephonyManager;

move-result-object v1

.line 81
.local v1, telephonyManager:Landroid/telephony/TelephonyManager;
const-string v0, ""

.line 82
.local v0, imei:Ljava/lang/String;
if-eqz v1, :cond_c

.line 83
invoke-virtual {v1}, Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;

move-result-object v0

.line 85
return-object v0
.end method

「Landroid/telephony/TelephonyManager;->getDeviceId()」からIMEIを取得している事がわかります。
つまり"&hid="はIMEIのパラメータが入っているということですね。
さぁ、こうやって一つ筒見ていくと、このUrlBuilderは以下の文字列を生成します。

&ua=(UserAgent)&pub=(publisherId)&spot=(SpotId)&site=(SiteId)&ll=(Location)&country=&pc=postalCode&mt-age=age&mt-gender=&mt-hhi=hhi&hid=(DeviceID)&a=(AdultContentType)&client-ip=(LocalIpAddress)&l=(Language)&c=3&version=(Version(広告モジュールのバージョン))&mt-speed=(ConnectionType)&mt-jtlib=(JtLibVer(広告モジュールのライブラリバージョン))&mt-bundle=(BundleVersion)&mt-os=(Os)&mt-osversion=(SDKVersion)&mt-model=(AndroidModel)&mt-make=(android.os.Build.Brand)&mt-fw=(KernelVersion)&mt-operator=(OperatorName)&mt-nradio=(NetworkType)&mt-dradio=(PhoneType)&mt-subno=(SubscriberId)&

…パラメータ名を見てドキッとしました。postalCodeとかAgeとかgenderとか…
固定値もしくはNullが入っているようですが、パラメータが多すぎて調べきれない…
いずれにしても広告モジュールの仕組みではこれらのパーソナルデータを送信する為のパラメータが用意されているということだけでもかなり凶悪です。
今日のところはこのくらいにしておきます。(小出しですいません)

あ、それから実機の通信データをキャプチャしていただける方緩募です。


※調査中ですが、パラメータの内容をメモ
&ua=(UserAgent)android.webkit.WebView.getSettings()
&pub=(publisherId)(JtAdWidgetSettings内のパラメータに依存。デフォルトNull)
&spot=(SpotId)(JtAdWidgetSettings内のパラメータに依存。デフォルトNull)
&site=(SiteId)(JtAdWidgetSettings内のパラメータに依存。デフォルトNull)
&ll=(Location)android.location.LocationManager.getLastKnownLocation()
&country=(Country)(JtAdWidgetSettings内のパラメータに依存。デフォルト"")
&pc=(postalCode)(JtAdWidgetSettings内のパラメータに依存。デフォルト"")
&mt-age=(age)(JtAdWidgetSettings内のパラメータに依存。デフォルト"")
&mt-gender=(gender)(JtAdWidgetSettings内のパラメータに依存。デフォルト"")
&mt-hhi=(hhi)(JtAdWidgetSettings内のパラメータに依存。デフォルト"")
&hid=(DeviceID)android.telephony.TelephonyManager.getDeviceId()
&a=(AdultContentType)(JtAdWidgetSettings内のパラメータに依存。デフォルト"notallowed")
&client-ip=(LocalIpAddress)java.net.NetworkInterface.getInetAddresses()
&l=(Language)(JtAdWidgetSettings内のパラメータに依存。デフォルト"en")
&c=3
&version=(Version(広告モジュールのバージョン))
&mt-speed=(ConnectionType)"WiFi"or"3G"
&mt-jtlib=(JtLibVer(広告モジュールのライブラリバージョン))
&mt-bundle=(BundleVersion)(JtAdWidgetSettings内のパラメータに依存。デフォルト"com.jumptap.adtag-android")
&mt-os=(Os)(JtAdWidgetSettings内のパラメータに依存。デフォルト"Linux")
&mt-osversion=(SDKVersion)android.os.Build$VERSION.RELEASE
&mt-model=(AndroidModel)android.os.Build.DEVICE
&mt-make=(Brand)android.os.Build.Brand()
&mt-fw=(KernelVersion)(/proc/versionから取得)
&mt-operator=(OperatorName)android.telephony.TelephonyManager.getNetworkOperatorName()
&mt-nradio=(NetworkType)android.telephony.TelephonyManager.getNetworkType()
&mt-dradio=(PhoneType)android.telephony.TelephonyManager.getPhoneType()
&mt-subno=(SubscriberId)android.telephony.TelephonyManager.getSubscriberId()