日本ソフトウェア科学会第 33 回大会 (2016 年度) 講演論文集

階層的グループ化に基づき Android アプリの安全性を向上するバイトコード書換えツール
馬谷 誠二

藤原 康史

五十嵐 淳

スマートフォン中の機密情報の漏洩を防ぐには，Android アプリの安全性が非常に重要である．Android アプリは一般的にバイトコードで配布されるため，バイトコードレベルの書換え操作によってアプリの「危険な」動作を検出・ブロックする手法が有効であり，これまでいくつか提案されている．本発表では，比較的単純な書換えでありな
がら適度な柔軟性を兼ね備えた，安全性向上のためのバイトコード書換えツールを提案する．提案手法によって生成されるバイトコードは，ユーザが階層構造として指定するセキュリティポリシーに基づきオブジェクトを階層的にグループ化し，グループ単位で参照を有効/無効化する仕組みによってリソース間の情報の流れを適切に管理する．

In order to prevent confidential information from being leaked outside smartphones, the secrecy about every
installed Android application is essential. Since most Android applications are packaged and deployed in
bytecode format, several previous studies have focused on rewriting the application’s bytecode at installation time for detecting and blocking its ‘dangerous’ behaviors. In this presentation, we propose a bytecode
rewriting tool which uses some simple rewrite processes while having the appropriate flexibility for realizing
various security policies. The rewritten bytecode partitions resources (objects) into several hierarchicallystructured groups, according to the user-specified security policy, and then manages information flows among
resources using the runtime mechanism that enables dynamic revoking of inter-group references.

の機構にはいくつかの問題が存在する．まず，アプ

1 はじめにリケーションに対するリソースへのアクセスの許可

近年，スマートフォンなどの多機能携帯端末が広（パーミッション）は，そのアプリケーションがインく普及するにつれ，重要なデータを携帯端末に入れストールされるタイミングで付与される．その後，端たまま持ち運んだり，そこからインターネット経由で末ユーザが明示的に許可を取り消さない限り，アプリ

送信することが増えている．そのため，モバイルア

ケーションはそのリソースにずっとアクセスしつづけ

プリケーションや携帯端末上の OS などのソフトウェることができる．また，Android が標準でサポート

アの脆弱性をついた攻撃による機密データの流出は，しているリソースや許可の種類は固定されており，端一般の人にとって身近で深刻な問題となっている．

末ユーザやアプリケーション開発者は，それ以外のリ

一般に普及している携帯端末プラットフォームでソースアクセスを制御できない．それに加え，標準である Android には，アプリケーションから端末上の用意されている許可の中には，複数の関連するリソー

様々なリソースへのアクセスを制御するためのパースをまとめて制御するものがあり，その中の一部のリミッション機構が備わっている．しかしながら，標準ソースにだけ許可を出す等，きめ細かな制御を行えない．

∗

Bytecode Rewriter for Improving Security of Android Applications based on Hierarchical Grouping.
This is an unrefereed paper. Copyrights belong to
the authors.
Seiji Umatani, Yasufumi Fujiwara, Atsushi Igarashi,
京 都 大 学 大 学 院 情 報 学 研 究 科, Graduate School ofInformatics, Kyoto University.

これらの問題を解決する先行研究として，Android
プラットフォームの内部を修正することによって，ア
プリケーションに付与した許可を柔軟に変更できるようにする方法 [2] や，リソースアクセスをより細かな単位で制御できるようにするための方法が提案されている [1]．しかしながら，これらの方法ではプラッ

きめ細かくデータの流れを監視することができる．

トフォーム内部の実装を修正しているため，標準の本論文の構成は以下のとおりである．まず，2 章

Android プラットフォームを利用している限り用い

では，簡単な Android アプリケーションを例に挙げ，ることができない．また，リソースアクセスをより細本研究が対象とする情報漏洩について述べる．次に，

かな単位で制御できるようにする先行研究の多くは，

3 章では，提案する階層的データ保護モデルについて

単一リソースへアクセスするための API 呼び出しを説明する．4 章では，書換えの対象である Dalvik バ

制御するだけであり，リソース間のデータの受け渡し

イトコードについて簡単に紹介した後，提案ツールのは監視しない．そのため，あるリソースから取り出し

書換え手順について述べる．5 章では，書換え後のア

た機密データを別のリソースを経由して外部へ漏洩

プリケーションの動作確認と実行時間の測定結果につさせるといった類の情報漏洩を防ぐことはできない．

いて触れる．最後に，6 章でまとめと今後の課題につそこで，本研究ではリソース間のデータの流れを動いて述べる．

的に制御するための階層的データ保護モデル，および，Android アプリケーションが階層的データ保護

2 リソースアクセスの簡単な例

モデルに基づいて動作するようアプリケーションを自たとえば，図 1 のようなリソースアクセスを行う

動で書き換えるツールを提案する．

アプリケーションを考える．この例は，電話帳から閲提案する保護モデルでは，複数のリソース（オブ覧時に端末に表示される登録名を取得し，作成したジェクト）を内部に含む「部屋」の概念を用いる．モ

通信用ソケットに書き込むプログラムである．1 行目

デルには複数の部屋が存在するが，各リソースは必でソケットオブジェクトを生成し，7 行目で生成したずどれか一つの部屋に含まれており，プログラム実行

カーソルオブジェクトを用いて取得したユーザの電話

中，別の部屋へ移動することはない．また，プログラ帳に含まれる文字列情報 (13 行目で取得) を次々にソムはいずれかの部屋の中にいる状態で実行され，そのケットへ書き込んでいる (14 行目)．

部屋に含まれているリソース以外へはアクセスでき

このアプリケーションを正常に動作させるには，アず，他の部屋のリソースへアクセスするには，先に明プリケーションのインストール時にユーザから適切な

示的な移動を行わなければいけない．このような制

許可を与える必要がああり，そのため，アプリケーショ限を設けることで，別々の部屋に置かれたリソース間ン設定情報の記述されている AndroidManifest.xmlのデータの自由な受け渡しを抑制することができる．

には以下のようなパーミッション要求が書かれている．

提案モデルでは，さらに部屋の間に親子関係を設け，<uses-permission android:name=

部屋全体を階層構造により管理する．プログラムは，階層のルートから特定の部屋へ至るパスに含まれる"android.permission.INTERNET" /><uses-permission android:name=

全ての部屋に属するリソースへのみアクセスできる．

"android.permission.READ_CONTACTS" />このようにすることで，排他的に管理したい異なるリ

しかしながら，このようなパーミッション機構にソースを別の部屋に置いたまま，それらの両方と同時

はセキュリティ上の問題が存在する．まず，一旦パーに使用したいリソースを共通の親にあたる部屋に配ミッションが与えられると永続的にそのリソースを使置する等，アプリケーションのリソース利用に応じたうことができ，リソースの使用に対し，回数や期間な柔軟な構成が可能となる．

どの制限を課すことができない．また，パーミッショ

提案するツールは，アプリケーションをこのモデル

ンも Android が固定で定めた標準のものしか用意あも用いるコードへと書き換えることで，動的にデーれておらず，端末ユーザやアプリケーション開発者がタの流出の監視を実現する．プラットフォームの内部

リソースアクセスを細かく制御することはできない．

を変更しないため通常の Android 上で利用可能であ

たとえば，図 1 のコードを動作させるために電話帳

り，また，動的にデータの流れを追跡することによりデータの読み出しのパーミッションと外部接続のパー1: Socket s = new Socket(IP,12345);
2: BufferedWriter writer =3:
new BufferedWriter(4:
new OutputStreamWriter(5:s.getOutputStream()));
6: Cursor c = contentResolver.query(
7:
Contacts.CONTENT_URI,
8:
new String[] {9:Contacts._ID, Contacts.LOOKUP_KEY,
10:
Contacts.DISPLAY_NAME }, ...);
11: while (c.moveToNext()) {12:
c.moveToPosition(-1);
13:
String displayName = c.getString(2);14:writer.write(displayName);
15: }16: writer.close();17: s.close();
図1

リソース使用コードの例

2 つ目は，パーミッションの細分化である．これは，標準で与えられるパーミッションをさらに細かく分類
し，アプリケーションが本当に必要とするリソースア
クセスを超える権限以を与えないようにするものである．たとえば，文献 [1] では，位置情報の取得要求に対し，大雑把な位置情報を返すパーミッションと詳
細な位置情報を返すパーミッションに分けることにより，必要以上に詳細な位置情報を取得できないようにしている．
しかしながら，これらの先行研究の手法にはいく
つかの問題が存在する．まず，どちらの手法においても，一旦パーミッションを与えられたアプリケーショ
ンは，対応する個々のリソースを自由に使用することができる．そのため，複数のリソースへのアクセス許可を同時に与えた場合，ユーザにとっては望ましくなミッションを付与している場合，このアプリケーショ

いリソース間の情報の受け渡しまで許してしまう可ンは任意のタイミングで外部との通信を行え，なおか

能性が生じる．たとえば図 1 の例の場合，仮に電話

つ，ユーザが意図しないデータさえ外部に送信でき帳に含まれる特定の情報のみをソケットに書き込むこてしまう．さらに，Android バージョン 6.0 以前にとだけに対しユーザは許可を与えたいとしても，アプ

おいては，パーミッションはインストール時にまとめ

リケーションにソケット (と他の機密情報を取り出すてユーザの許可を求めるようになっており，ユーザがリソース) への権限を付与してしまっては，ソケット

個々のリソースアクセスが適切なものかどうかを確認にそれ以外の情報を書き込むことを禁止することはしないまま与えてしまう場合も多い．さらに，アプリ

不可能である．

ケーション開発者が本来必要のないパーミッション要
求をマニフェストに記載している場合も多く存在す

3 階層的データ保護モデル

る．このように，Android が標準で提供するパーミッ

前章で触れたような既存手法の問題を解決するたション機構にはセキュリティ上の問題が多く，解決すめ，我々はリソース同士を互いにを隔離するモデルとるために様々な提案がなされている．

して階層的データ保護モデルを提案する．このモデル

パーミッション機構の改良に関する先行研究は大きく次の 2 つに分けられる．

は複数のリソースを隔離するためのモデルであり，あるリソースへアクセス可能でありながら，別のリソー

1 つ目は，Android 標準のパーミッション機構の修スにアクセス不可能であるという状況を実現する．

正に関する研究である．Android ではインストール

このモデルを用いることで，機密情報を取得し得る時に一括でパーミッションを許可するため，ユーザのリソースと情報を外部へ流出し得るリソースを隔離

判断が難しくなっているが，インストール時に複数アすることで，機密情報の流出を防ぐことが可能にな

プリケーションにまたがる情報の流れを調べ，すでにる．たとえば，電話帳にアクセスするための Cursor

インストールされているアプリケーションと組み合わ

オブジェクトとネットワークにアクセスするためのせた場合の安全性まで考慮する研究 [3] や，付与する

Socket オブジェクトを隔離することで，電話帳へのパーミッションにリソースの使用回数や使用期間に上アクセスの許可とネットワークアクセスの許可の両方限を設けることで，無期限かつ無制限に使えなくするをアプリケーションに与えている場合でも，電話帳のような研究 [2] がある．

情報がネットワークへ流出することをを防ぐことができる．

3. 1 部屋
まず始めに，階層的データ保護モデルで用いられる部屋の概念を導入する．部屋には複数のオブジェクトが登録され，複数の部屋に同じオブジェクトは登録で

図2

部屋の概念

きない．またプログラムは現在いる部屋に登録されているオブジェクトのみにできる．また，プログラム実
行中に生成されるオブジェクトは現在いる部屋に登録され，外へ持ち出すことはできない (正確には，部屋の外にいる状態でのアクセスは無効となる)．
このようなモデルに基づき，排他的にアクセスされるべき複数のオブジェクトを異なる部屋に登録することで，同時にアクセスすることを禁止することができる．たとえば図 2 では，プログラムは Room1 の中で実行しているためオブジェクト A にはアクセスできるが，一方，異なる部屋に登録されているオブジェ

図3

部屋の階層構造

クト B へはアクセスできない．
このモデルを用いることで，必要なリソースへの最部屋をこのような階層構造で管理することで，ある低限のアクセスを可能にしながらも，特定のリソー

リソースを複数の異なる部屋で用いることが可能となスの組み合わせに対する同時アクセスを禁止できる．

る．たとえば図 3 のように，A と B，C と D を排他的

たとえば，図 1 のプログラムを変更し，電話帳からにアクセスしたいが，B と C，B と D は同時にアクセ取得した文字列データをネットワークに流出させたくスしたい場合にはこのように配置する．これは，部屋ない場合，Socket オブジェクトと Cursor オブジェの構造がフラット，かつ，あるデータを単一の部屋にクトを別々部屋に登録することで，それらへの同時アしか登録できないという制約の元では実現できない．

クセス，すなわち，それらオブジェクト間の情報の受け渡しを禁じることができる．

3. 3 Java による実装
Android のアプリケーションは Java で書かれてい3. 2 部屋の階層化るため，提案モデルを Android アプリケーションに階層的データ保護モデルでは，部屋を入れ子状 (樹対して用いるには，前節で説明した部屋の概念を Java状) に配置し，根を一番外側の部屋，子を親の部屋のの実行モデル上で実現する必要がある．Android に内部にある部屋として配置する．このとき，プログラ

おいてリソースはすべてオブジェクトとして表現さ

ムは現在いる部屋に所属するオブジェクトに加え，それるため，排他的にしたい複数のリソースに対応すの部屋の祖先である部屋に所属するすべてのオブジェ

るオブジェクト同士を隔離することで，リソースアククトへもアクセスできるものとする．そのため，たとセスの隔離を実現する．そこで，一般的なプロキシオ

えば根の部屋に属するオブジェクトは，任意の部屋か

ブジェクトによる手法を用いる．プロキシオブジェク

らアクセス可能である．

トとは，メソッドを呼び出す側と呼び出されるメソッ

たとえば図 3 では，Room1 で実行中，オブジェクト

ドを持つオブジェクトの間に存在するオブジェクトでX，A，A2 へはアクセス可能であり，Room4 で実行中あり，呼出し先のオブジェクトが設定されている場合

は，オブジェクト X，B，D にアクセス可能である．

に限り，そのオブジェクトにメソッド呼出しを転送す1: public class SampleProxy extends Sample
2:
implements IProxy {3:protected boolean flag;
4:
public Room belong;5:
public SampleProxy() {6:this.flag = true;
7:
this.belong = Room.getnowroom();}8:
public Sample get() {9:if (!flag) System.exit(1);10:return (Sample) this;
11:
}
12:
public void samplemethod() {13:
if (!flag) System.exit(1);14:super();
15:
}
16: }
図4

プロキシオブジェクトの実装

る．そのような動作を利用して，プロキシオブジェク
ト内部にアクセス可否のフラグを持たせ，フラグがアクセス可であれば呼出しを転送し，アクセス不可であれば呼出しを遮断することにより，動的なリソースア
クセスの可否の切替えを実現する．
また，部屋自身も Java のオブジェクトとして表現される．部屋に所属する各オブジェクトに対応するプ
ロキシオブジェクトは，部屋オブジェクトが内部で管

1: Room socketroom = new Room();
2: Room cursorroom = new Room();
3: Room.enter(socketroom);
4: SocketProxy s = new SocketProxy(5:
new Socket(IP,12345));
6: BufferedWriterProxy writer =7:
new BufferedWriterProxy(8:
new BufferedWriter(9:
new OutputStreamWriter(10:s.getOutputStream())));
11: Room.enter(cursorroom);
12: CursorProxy c = new CursorProxy(13:
contentResolver.query(
14:
Contacts.CONTENT_URI,
15:
new String[] {16:Contacts._ID,
17:
Contacts.LOOKUP_KEY,
18:
Contacts.DISPLAY_NAME }, ...));
19: while (c.moveToNext()) {20:
Room.enter(cursorroom);
21:
c.moveToPosition(-1);
22:
String displayName = c.getString(2);23:
Room.enter{socketroom};24:
writer.write(displayName);
25: }26: Room.enter(socketroom);
27: writer.close();28: s.close();
図5

提案モデルを利用するコードの例

理しているプロキシリストに登録される．プログラ
ムは，実行中，部屋オブジェクトとプロキシオブジェ

ロキシオブジェクトである s と BuffrerdWriter ク

クトからなる単一の木構造を保持し，実行中の部屋間

ラスのプロキシオブジェクトである writer を生成しの移動は，木構造を使って移動先の部屋からアクセスている．これらのオブジェクトは socketroom に自動可能な部屋の集合および不可能な部屋の集合をそれで登録される．同様に，Cursor クラスのプロキシオ

ぞれ求め，それらの部屋に属するプロキシ中のアクセ

ブジェクトを cursorroom 中で生成・登録し，その後ス可否フラグを適切に切り替えることで実現する．

は，オブジェクトの代わりにプロキシオブジェクトを

プロキシクラスの具体的な実装を図 4 に示す．な

経由してそれらのリソースにアクセスする．プロキシ

お，SampleProxy は Sample クラスのためのプロキ

オブジェクトにアクセスしたい場合には，プログラム

シクラスであり，Room クラスは部屋オブジェクトのは事前に適切な部屋へ移動する必要がある．

実装クラス，IProxy インタフェースはすべてのプロキシクラスに共通するインタフェース定義である．

4 バイトコード書き換えによる実現

図 1 の コ ー ド に 対 し ，Socket オ ブ ジェク ト と本章では，Android アプリケーションの実行形式

Cursor オブジェクトを隔離したい場合，提案モデルをである Dalvik バイトコードを書き換えることで，前用いると図 5 のようなコードとなる．1,2 行目で root

章の提案モデルに基づく振舞いをアプリケーションにを親に持つ 2 つの部屋 socketroom，cursorroom を追加する方法について説明する．

生成し，3 行目でプログラムはまず socketroom に入り，4,5 行目で socketroom 中で Socket クラスのプ

4. 1 Dalvik バイトコード

type ids 領域のインデックス，およびメソッド名のまず，Dalvik バイトコードについて簡単に説明

string ids 領域のインデックスが格納されている．

する．

class defs 領域にはクラスの情報が格納されている．

Android アプリケーションは apk ファイルと呼ばクラス型のインデックス，アクセス属性のフラグ値，れるファイル形式で配布され，Android 端末にイン親クラス型のインデックス，継承インタフェース型

ストールされる．apk ファイルは，アプリケーションのリストのオフセット，ソースファイル名の文字列のが必要とするリソースアクセス許可などの実行に必要

インデックス，アノテーション情報へのオフセット，な情報が書かれたマニフェストファイル，dex ファイ

class data へのオフセット，静的フィールドの初期値

ル，認証のための署名関連のファイル，およびリソーを含む．

スファイルを zip により圧縮したものである．この中data 領域は，上記すべてを含むサポートデータ用

で，dex ファイルがプログラムの実行可能ファイルにのデータ領域である．レイアウト情報，文字列デー

相当し，Java のソースコードをコンパイルしたクラタ，型識別子のリスト，アノテーション関連の情報，

スファイルからさらに専用のコンパイラを用いてコンクラス情報，メソッドのバイトコードの情報，デバッ

パイルすることにより作成される．

グ情報が含まれる．

dex ファイルのフォーマット
dex ファイルのフォーマットについて説明する．
dex ファイル全体は，header, string ids, type ids,
proto ids, field ids, method ids, class defs, data,link data の９つの領域で構成される．
header 領域は dex ファイルのヘッダ部分であり，ファイルサイズ等，このファイルの構成に関する情報が含まれている．

string ids 領域は，定数文字列の ID を格納している．

type ids 領域には，型名を表す文字列の ID を格納している．V，Z，B，S，C，I，J，F，D はそれぞれ

Java のプリミティブ型，L⟨classname⟩; は参照型，[⟨typename⟩ は配列型を意味する．
proto ids 領域にはメソッド型のテーブルが格納さ

link data 領域は，静的にリンクされるファイルにおいて使用されるデータ領域である．

class defs 領域のオフセットの指す class data 領域には，メソッドとフィールドの数，フィールド情報，
コンストラクタ，静的メソッドや仮想メソッドの情報が格納されている．その中のメソッド情報には，メ
ソッド id，アクセスフラグ，コード構造体へのオフセットが含まれており，コード構造体には，メソッドが使用するレジスタ数やメソッドを構成するバイトコード列などが含まれる．このコード構造体が提案手法の主な書き換え対象である．

Dalvik バイトコード
バイトコード命令の一覧を表 1 に示す．ただし，以降の説明と無関係な一部の命令については省略している．

れており，型名を表す文字列を含む string ids 領域のインデックス，返り値型の type ids 領域のインデッ

4. 2 実行時クラス

クス，パラメータ型のインデックスが含まれる．

Room クラスと IProxy インタフェースの実装コー

field ids 領域にはフィールドの情報が格納されておドについては，まず始めに Java で書かれたソース

り，フィールドを持つクラスの型の type ids 領域のファイルを通常の方法により dex ファイルへ変換す

インデックス，フィールドの型の type ids 領域のイる．作成した dex ファイルは，アプリケーションのンデックス，およびフィールド名の string ids 領域の書き換え時にアプリケーションの dex ファイルと一

インデックスで構成されている．

つに結合される．各アプリケーションの実装コード中

method ids 領域には，メソッドを所有するクラスの proto ids 領域のインデックス，メソッドの型のへは，これら 2 つで定義されているメソッドの呼出し等が挿入されることになる．

表1

op コード
01–03
07–09

Dalvik バイトコード命令一覧（一部）

命令フォーマット
move v1 v2

move-object v1 v2

0a
0c
0e
12
1a
1c

move-result v1
move-result-object v1
return-voidconst/4 v1 A
const-string v1 A
const-class v1 A

1fcheck-cast v1 A

20

instance-of v1 v2 A

21
22
23

array-length v1 v2
new-instance v1 A
new-array v1 v2 A

32-37
44-51

if-test v1 v2 A
arrayop v1 v2 v3

52-5f

iinstanceop v1 v2 A

60-6d

sstaticop v1 A

6e-72

invoke-kind {v1,. . . ,vn} A

74-78

invoke-kind/range {v1,. . . ,vn} A

7b-8f
90-af

unop v1 v2
binop v1 v2 v3

説明
オブジェクトでない v2 レジスタの中身を v1 レジスタに移動する．
命令により移動元，移動先のレジスタ番号のサイズが異なる．
オブジェクトの v2 レジスタの中身を v1 レジスタに移動する．
命令により移動元，移動先のレジスタ番号のサイズが異なる．
1 ワードのオブジェクトでない返り値をレジスタ v1 に移動する．
オブジェクトの返り値をレジスタ v1 に移動する．
返り値のないメソッドから戻る．
4bit の A の値を 32bit に拡張しレジスタ v1 に格納する．
A のインデックスで指定された string を v1 のレジスタに格納する．
A のインデックスで指定された type のクラスへのリファレンスを
v1 のレジスタに格納する．
v1 に格納されているオブジェクトを A のインデックスで指定された型にキャストできるか確かめる．できない場合は ClassCastException が投げられる．
v2 に格納されているオブジェクトが A のインデックスで指定された型のインスタンスであるかを v1 のレジスタに格納する．
v2 で指定された array の長さを v1 に格納する．
A のインデックスで指定された型のインスタンスを v1 のレジスタに格納する．
A のインデックスで指定された型の v2 のレジスタに格納されているサイズの array を作成し v1 のレジスタに格納する．
v1 と v2 を比較し，A のブランチにジャンプする．
aget の場合 v2 のレジスタの array の v3 のレジスタのインデックスの内容をv1 に格納する．aput の場合は v2 のレジスタの array の v3 のレジスタのインデックスに v1 のレジスタの内容を書き込む．
iget の場合は v1 のレジスタに A のインデックスで指定されたフィールドの内容を格納し，iput の場合はレジスタの内容をフィールドに書き込む．
sget の場合は v1 に A のインデックスの
スタティックフィールドの内容を格納する．
sput の場合は A のインデックスのスタティックフィールドに v1 レジスタの内容を書き込む．
A のインデックスで指定されたメソッドを引数 v1,. . . ,vn で実行し結果を return レジスタに格納する．
v1 から指定された数の引数で A のインデックスで指定されたメソッドを実行し，結果を return レジスタに格納する．
v2 のレジスタの値に単項の演算をして v1 のレジスタに格納する．
v2 のレジスタの値と v3 のレジスタの値を演算して結果を v1 のレジスタに格納する．

Room クラスは，現在位置している部屋と親の部屋

部屋オブジェクトを作成する．multiEnter メソッド

オブジェクトへの参照，部屋に所属するプロキシオブ

は，任意個数のオブジェクトを引数にとり，IProxy

ジェクトのリストへの参照を持つ．また，Room クラ

インタフェースを実装しているオブジェクトの所属すスの静的フィールドとして，プログラム実行中に生る部屋を取得し，それらの部屋と実行時にプログラム

成済みの全ての部屋を含むリストが格納されている．

が位置する部屋のうち，最も階層の深い部屋へ入る．

Room クラスには enter メソッド，createRoom メソッ

IProxy インタフェースには，抽象メソッドとしてド，multiEnter メソッドが用意されている．enterget メソッドが定義されている．これは個々のプロキ

メソッドは，引数として受け取る部屋からアクセス可

シクラスで実装され，本来のオブジェクトへの参照を

能なプロキシオブジェクトのフラグをアクセス可に取得するために用いられる．プロキシオブジェクト

し，ほかのプロキシオブジェクトのフラグをアクセス

は，生成時にプログラムが位置している部屋の所属リ不可にするものである．また，createRoom メソッド

ストに登録される．

は，引数として受け取る部屋オブジェクトを親とする

4. 3 アプリケーションコードの書き換えメソッドの呼び出しに対し，引数オブジェクトがDalvik バイトコードに対する書き換え手順の詳細

プロキシオブジェクトなら引数として渡す直前にを述べる．以下では，主に code item 領域内に含ま

元のオブジェクトを取り出し，さらに受け取ったれる各メソッド本体の命令列である instr リストに対返り値をプロキシオブジェクト化する処理を追加する処理について説明するが，クラスやメソッドを追する．

加登録する際には，適宜，適切な他の領域にもデータ

上記の手順ににより，アプリケーションが階層的デーを追加登録するものとする．

タ保護モデルを用いるように書き換えられる．以下，階層的データ保護モデルを用いるようにアプリケー

各手順を詳細に説明する．

ションを書き換える大まかな手順は，次のとおりで

4. 3. 1 ライブラリとの統合

ある．

プ ロ キ シ オ ブ ジェク ト の イ ン タ フェー ス で あ る

1. プロキシオブジェクトを登録するための部屋とIProxy インタフェースおよび部屋の概念の実装であ

プロキシオブジェクトのインタフェースを実装しる Room クラスの実装を含む dex ファイルと，書き換

た dex ファイルを，アプリケーションの dex ファ

え対象アプリケーションの dex ファイルを結合する．

イルと結合する．

結合する際，id がかぶらないように再度割り当てな

2. プロキシオブジェクトを作成するクラスの情報

がら，二つの dex ファイルに存在するクラス，メソッを読み出し，フラグがアクセス可であれば元のオド，フィールド，型を登録する．この処理を行うこと

ブジェクトと同じ動作をし，アクセス不可であれ

で，アプリケーションの dex ファイルから IProxy やばアクセスを遮断するようなプロキシクラスのRoom を利用することができるようになる．

定義を生成する．

4. 3. 2 プロキシクラス定義の生成

3. ユーザが相互排他的にアクセスするべきである

dex ファイル中の部屋に登録される可能性があるオと指定したクラスの組の集合と，アプリケーショ

ブジェクトのクラス定義から，プロキシオブジェクト

ン実行中に同時に用いられるオブジェクトの組合のクラス定義を作成する．元のオブジェクトのクラス

せ（たとえばあるメソッド呼出しの引数に同時に定義に final 属性がついているかどうかに従い手順含まれているなど）の集合から，適切な部屋の階が異なる．また，Dalvik バイトコードにクラスを登

層構造を求め，アプリケーションの開始時に実行録する処理は，名前の登録や型の登録をファイル構成

されるコードへ必要な部屋を生成するコードを順に行い，dex ファイル全体の整合性が保たれるよう挿入する．

に注意しなくてはならない．

4. 部屋に所属させるべきオブジェクトのインスタ

final 属性がついていない場合，プロキシクラスは

ンス生成命令を，プロキシオブジェクトのインス

元のクラスのサブクラスとして定義する．フィールド

タンス生成の命令に置き換え，さらに，プロキシにアクセス可否のためのフラグを追加し，コンスト

オブジェクトのコンストラクタを呼び出す処理を

ラクタを実装する．また，元のオブジェクトのメソッ

追加する．

ドをオーバーライドするメソッドを登録し，フラグを

5. プロキシオブジェクトのインスタンス生成命令

チェックした後，スーパークラスのメソッドを呼び出の直前に，登録すべき部屋へ移動するメソッド呼すという処理を追加する．こうすることで，プロキシ

び出しを挿入し，また，プロキシオブジェクトをクラスに対してメソッド呼び出しが行われた際に，処引数として受け取るメソッド呼び出しの直前に，理を元のクラスのメソッド呼び出しに転送することがそのプロキシオブジェクトが属する部屋へ移動すできる．さらに，手順 6 の実現に必要となる，元のオ

るための Room クラスのメソッド呼び出しを挿入

ブジェクトを返す get() メソッドを実装する．

する．

6. 引数として通常のオブジェクトを受け取る外部

final 属性がついている場合，プロキシクラスの定義は，元のオブジェクトへの参照を保持するフィールド target を含むようにする．また，フィールドに変換後:アクセス可否のためのフラグを追加し，適切なコン

new-instance v2,LSecret;

ストラクタを実装する．さらに，元のオブジェクトのinvoke-direct {v2,v1},LSecret;-><init>()クラスが持つ全てのメソッドと同名のメソッドを定

new-instance v0,Lproxy/SecretProxy;

義する．それらのメソッドは，フラグをチェックした

invoke-direct {v0,v1},Lproxy/SecretProxy;

後，target に格納されているオブジェクトのメソッ-><init>(LSecret;)

ドを呼び出す．get() メソッドの実装については同様

move-object v2,v0

である．

追加したコードは新たなレジスタを確保し，そこに

4. 3. 3 メソッド引数型の変更

新しいプロキシオブジェクトのインスタンスを生成書き換えたコードでは，すべてのオブジェクトの参する．その後，引数に Secret オブジェクトを受け取

照はプロキシオブジェクトの参照に置き換えられる

り，プロキシオブジェクトを生成し，コンストラクタ

ので，そのままではメソッドの引数としてプロキシオ

を呼び出し，結果を元のオブジェクトの格納先のレジ

ブジェクトが与えられる．プロキシオブジェクトを引スタに格納するという動作を行う．

数として与えると，メソッド呼び出しで指定されてい4. 3. 6 部屋間の移動コードの挿入る型と一致せず，例外が発生する．そのため，メソッ

部屋を引数に受け取り，その部屋に移動する enter

ドが受け取る引数の型を変更し，プロキシオブジェク

メソッドとオブジェクトのリストを引数に受け取り，

トを引数として受け取るようメソッドの引数型を書きそのうち，IProxy インタフェースを実装しているオ

換える必要がある．

ブジェクトの所属している部屋と今いる部屋のうち，

4. 3. 4 部屋生成コードの挿入

一番階層の深い部屋に入る multiEnter メソッドを挿アプリケーション起動時に呼び出される onCreate()

入する．さらに，プロキシオブジェクトの生成の直前

メソッドの先頭に，部屋を生成するメソッドであるに enter メソッドを挿入し，プロキシクラスに属す

createRoom() メソッドを呼び出すコードを挿入する．

るメソッド呼び出し命令もしくは引数にプロキシオ

4. 3. 5 プロキシオブジェクトの挿入

ブジェクトをとるメソッドの呼び出し命令の直前に，保護するオブジェクトの参照にプロキシオブジェク

multiEnter メソッドを挿入する．

トを挟むため，オブジェクト生成のタイミングで，レ

以下，部屋の移動をするメソッドの挿入の例を示す．

ジスタに格納するオブジェクトへの参照を，そのオ変換前:ブジェクトへの参照を含むプロキシオブジェクトへのnew-instance v2,LSecret;

参照に置き換える．ここでは例として，Secret クラ

invoke-direct{v2,v1},LSecret;-><init>()Vスのオブジェクトを保護したい場合のコードを示す．

new-instance v0,Lproxy/SecretProxy;

SecretProxy クラスは，手順 2 のプロキシクラス定義の生成で作成された Secret
クラスのオブジェクト

invoke-direct{v0,v1},Lproxy/SecretProxy;へ中継するプロキシクラスである．

move-object v2,v0

変換前:

この例は，Secret クラスのインスタンス生成にプロ

new-instance v1,LSecret;

キシクラスのインスタンス生成を挿入したコードであinvoke-direct {v1,v0},LSecret;-><init>()

るが，このコードに対しては，次のように enter メ

このプログラムは，Secret クラスのオブジェクトを生

ソッドを挿入する．ここで SecretProxy オブジェク

成するコードである．このコードに対し，SecretProxyトが所属するべき部屋はレジスタ v3 に格納されていオブジェクトへの参照をプロキシオブジェクトへのる Room オブジェクトであるとする．

参照へ置き換えるコードを挿入すると以下のように

変換後:

なる．

new-instance v2,LSecret;-><init>(LSecret;)V

invoke-direct{v2,v1},LSecret;-><init>()V
invoke-virtual {v3},Lproxy/Room;->enter(Lproxy/Room)Vとして a と b をとるメソッド呼び出しは部屋 B の中であれば正常に動作するが，部屋 A 中で実行されると停止する場合が考えられる．また，メソッドの返り

new-instance v0,Lproxy/SecretProxy;

値はプロキシオブジェクトになっているので，返り値

invoke-direct{v0,v1},Lproxy/SecretProxy;の型は IntProxy 型，つまり Int 型のプロキシオブ-><init>(LSecret)V
move-object v2, v0

ジェクトとなり，結果をレジスタに格納する命令はオ
ブジェクトの移動命令になる．

プロキシオブジェクトが生成される場合，そのオブ4. 3. 7 外部メソッド呼び出しへの対処

ジェクトが属すべき部屋がある場合は，その部屋に入バイトコード中に，書き換えることのできない外部るという処理を挿入している．この時，部屋の階層構

メソッドへの呼び出しが含まれる場合，引数に渡す直造を参照することで入る部屋を決定する．

前にもとのオブジェクトに戻す必要がある．そのため

次に，メソッド呼び出しに対して部屋の移動をするの書き換えの例を以下に示す．

メソッドを挿入する場合を示す．挿入先の例として，

変換前:

以下のようなプログラムを考える．

new-instance v2,LSecret;

変換前:

invoke-direct {v2,v1},LSecret;-><init>()V

invoke-virtual {v0..vn;},LSecret;invoke-static {v3},Lproxy/Room;->method(types)I->enter(Lproxy/Room)V

move-return v0

new-instance v0,Lproxy/SecretProxy;

このプログラムは v0,. . . ,vn を引数として Secretinvoke-direct {v0,v1},Lproxy/SecretProxy;

クラスの method という I 型を返すメソッドを呼び-><init>(LSecret;)V

出すコードである．なお types は引数の型であり，

move-object v2,v0

typeProxy は引数の型のプロキシ型である．このコー

invoke-virtual {v2},Lext/Ext;

ドに対し multiEnter メソッド呼び出しを挿入する->extmtd(LSecret;)LSecret2;と，以下のようになる．

move-return-object v4

変換後:

このコードは Secret クラスのオブジェクトを作成し，invoke-virtual {vp},Lproxy/Room;

作成したオブジェクトを引数に外部 ext.Ext クラス->multiEnter([Lproxy/IProxy)Vの extmtd メソッドを呼び出すコードに対し，プロキ

invoke-virtual {v0..vn;},Lproxy/SecretProxy;->method(typesProxy)Lproxy/IntProxy;

シオブジェクトの挿入が施された後のコードであるが，このままでは動作しない．なぜなら本来 Secretmove-return-object v0

クラスのオブジェクトが渡されるはずのメソッドにメソッドを呼び出す前に，所属する部屋，今いる部

SecretProxy クラスのオブジェクトが引数として渡屋，引数のオブジェクトが所属する部屋の中で一番階されているからである．ここで ext/Ext は書き換え層が深いものに入るという処理を挿入している．一番ることができない領域のクラスであるとし，Secret，深い部屋に入る関数を挿入している理由として，同Secret2 はともに保護するクラスであるとする．こじパス上に引数のオブジェクトが所属する部屋が複のとき，書き換え結果は以下のようになる．

数ある場合，どの部屋に入るかに従い，本来は動作す

変換後:るべきメソッド呼び出しを停止させてしまう可能性

new-instance v2,LSecret;が生じるからである．たとえば，部屋 A と A の子のinvoke-direct {v2,v1},LSecret;-><init>()V

部屋 B があり，部屋 A にオブジェクト a，部屋 B に

invoke-static {v3},Lproxy/Room;

オブジェクト b が登録されているとする場合，引数->enter(Lproxy/Room)Vnew-instance v0,Lproxy/SecretProxy;

表2

実行時間 (ms)invoke-direct {v0,v1},Lproxy/SecretProxy;
オブジェクト登録数

実行時間

部屋の移動なし

0.090

0

8.085

->get()LSecret;1

9.8

move-return-object v5

20

118

-><init>(LSecret;)
move-object v2,v0
invoke-virtual {v2},Lproxy/SecretProxy;

invoke-virtual {v5},Lext/Ext;->extmtd(LSecret;)LSecret;

サンプルアプリケーションに対して，二つのクラス

move-return-object v5のオブジェクトを排他にするという設定で書き換えを

new-instance v4,Lproxy/Secret2Proxy;

行い，実行した結果，Network クラスの所属する部

invoke-direct {v4,v5},Lproxy/Secret2Proxy;

屋で AddressBook クラスの部屋に所属するオブジェ-><init>(LSecret2;)V書き換えたコードでは，ext/Ext クラスの extmtd メ

クトを引数として参照したためアプリケーションはデータを送信せず動作を停止した．

ソッド呼び出しの引数として渡すレジスタ v2 に格納されている SecretProxy オブジェクトを Secret オ

5. 2 実行時オーバーヘッドの測定

ブジェクトに変換し，v5 のレジスタに格納する．そまた，オーバーヘッドの測定のために，部屋の切りの後，v5 レジスタの値を引数として extmtd メソッ

替えを繰り返しするサンプルアプリケーションを作

ドを呼び出し，結果を v5 レジスタに格納する．結果成した．サンプルアプリケーションを用いて，部屋にはプロキシオブジェクトではないため，プロキシオブ

登録しているオブジェクトがない場合，オブジェクト

ジェクトを挿入し，返り値のオブジェクトを格納して数が一つの場合，オブジェクト数が 20 の場合に部屋いたレジスタに格納するという動作をする．この挿の切り替えを一万回行ない, 時間を計測した． 実行入によって，外部のメソッドに渡される直前に引数の環境はシャープ製 Aquos phone Xx 302SH， OS は型として正しい型に戻されｓるので，メソッド呼び出

Android4.2.2 である．

しが正しく実行されるようになる．また，外部メソッ

その結果を，表 5. 2 に示す．なお，データは 10 回

ド呼び出しの返り値に対し，プロキシオブジェクトのの平均値である．計測時間内には部屋の移動以外の挿入も行うので，呼び出し以降のすべてのオブジェク処理は行っておらず，部屋の移動なしの計測時間は空

トアクセスはプロキシオブジェクトへのアクセスとし

ループの所用時間である．

て機能する．

この結果から部屋に登録されているオブジェクトの数，部屋の移動の回数が実行時間に大きな影響を与え

5 予備実験

ていることが分かる．現在の書き換えではすべてのメ

5. 1 漏洩検出機能の検証

ソッド呼び出しの前に部屋の移動をするメソッドを挿動作を確かめるため，複数のリソースへの同時アク入しているが，この挿入の箇所を減らすことで実行時セスを行うサンプルアプリケーションを作成し，書き間を短縮することができると予想される．また，部屋換えを行った．用いたサンプルアプリケーションではの登録数も実行時間に大きな影響を与えているため，電話帳からデータを取得し，返すメソッドを持つクラ保護する必要のないオブジェクトに対してのプロキシ

ス AddressBook とデータをネットワークに送信する

オブジェクトの挿入を削減することで変換コストと，メソッドを持つ Network クラスをもち，アプリケー

実行時間を削減できると推測される．

ション内で AddressBook クラスで取得したデータを

Network クラスのメソッドで送信する処理を行う．

の課題である．

6 まとめと今後の課題
本研究で，階層的データ保護モデルを用いるように Android アプリケーションを書き換え，実験する
ことでこのモデルがセキュア化に有効であることが示せた．また，書き換え後の，階層的データ保護モデルを用いる Android アプリケーションにおいて，部屋の切り替えの処理が実行時間に大きな影響を与えていることが分かった．この結果から，部屋の移動の処理を減らすことで実行時間のオーバーヘッドを縮小できると推測される．そのため，現実装では部屋の移動の処理はすべてのメソッドの直前に挿入されているので，必要ない部屋の移動を検出し，挿入を減らす
ことで実行時間を減らすことができると考えられる．
また保護する必要のないオブジェクトに関してはプ
ロキシオブジェクトの挿入の処理をせず，通常のオブジェクトとして扱うことで，実行時間を減らすことができることが期待される．これらの実装，検証は今後

参 考 文 献[1] Jeon, J., Micinski, K. K., Vaughan, J. A., Fogel,
A., Reddy, N., Foster, J. S., and Millstein, T. D.:
Dr. Android and Mr. Hide: fine-grained permissions
in android applications, SPSM’12, Proceedings ofthe Workshop on Security and Privacy in Smartphones and Mobile Devices, Co-located with CCS
2012, October 19, 2012, Raleigh, NC, USA, 2012,
pp. 3–14.
[2] Nauman, M., Khan, S., and Zhang, X.: Apex:
extending Android permission model and enforcement with user-defined runtime constraints, Proceedings of the 5th ACM Symposium on Information, Computer and Communications Security,
ASIACCS 2010, Beijing, China, April 13-16, 2010,2010, pp. 328–332.
[3] Shen, F., Vishnubhotla, N., Todarka, C., Arora,M., Dhandapani, B., Lehner, E. J., Ko, S. Y.,
and Ziarek, L.: Information flows as a permission mechanism, ACM/IEEE International Conference on Automated Software Engineering, ASE ’14,
Vasteras, Sweden - September 15 - 19, 2014, 2014,
pp. 515–526.