Paper - 京都産業大学

SCIS 2015
The 32nd Symposium on
Cryptography and Information Security
Kokura, Japan, Jan. 20 - 23, 2015
The Institute of Electronics,
Information and Communication Engineers
c
Copyright ⃝2015
The Institute of Electronics,
Information and Communication Engineers
メソッド呼び出しのフックを用いた動的コールフローグラフ偽装の試み
A Dynamic Diversity Method by Hooking Method Calls
稲垣 賢一 ∗
Kenichi Inagaki
福田 收真 †
Kazumasa Fukuda
玉田 春昭 ‡
Haruaki Tamada
あらまし 近年、不正解析によりソフトウェア内部の秘密情報が抜き出され、利用されるクラッキング
が深刻化してきている。このような中、不正解析からソフトウェアを保護するために、今日では多くの
難読化手法が提案されている。その中の一つに、我々の研究グループでは、以前に、静的解析に対抗す
るための手法として、コールグラフを偽装する手法を提案している。これは、メソッドのオーバーロー
ドを利用し、本来のメソッドとは別のメソッドを呼び出すように予め変更しておく。そして、実行時に
難読化されたメソッドが実行される直前に、引数の順序を入れ替えることで、本来のメソッドを呼び出
すようにする手法である。しかし、この手法は、静的解析に対しては有効であるものの、動的解析に対
しては脆弱であった。そこで本稿では、この手法を動的に適用するよう手法を拡張する。提案手法を評
価するために、プロトタイプツールを作成した。難読化前後の実行時間の変化を測定し、パフォーマン
スを評価した。パフォーマンス評価の結果、書き換え回数 500 で 2 秒から 3 秒程度の遅延が確認できた。
また、提案手法のステルシネスを評価し、提案手法を適用したプログラムの不自然さを評価した。不自
然さ評価の結果、難読化前後でのプログラムの不自然さの変化は小さいことが確認できた。そして、ク
ラスファイルをダンプするプログラムを用いて、提案手法の攻撃耐性を評価した。攻撃耐性評価の結果、
提案した手法はクラスファイルをダンプするプログラムに対して攻撃耐性があることが確認できた。
キーワード 難読化, コールフローグラフ, 動的多様化, メソッドフック
1
はじめに
読みにくくすることによって、不正解析やクラッキング
を妨害する技術である [2]。例えば、プログラム中の関
近年、ソフトウェアの不正解析によってソフトウェア
数名や変数名を意味のない文字列に置き換える名前難読
から秘密情報を抜き出し、利用する違法コピーが深刻化
化 [6] やループを複雑にしたりダミー命令を追加するこ
してきている。こうした不正解析からソフトウェアを保
とで処理の流れを複雑にするコントロールフロー難読化
護するために、ソフトウェアプロテクションの重要性が
[2] が挙げられる。多くの難読化手法は Java 言語向けに
提案されている。Java 言語はソースコードをコンパイ
高まっている。しかし、今日ではソフトウェアに施され
たプロテクトはクラックによって無効化されるケースが
ルすると、クラスファイルというバイナリ形式のフォー
増加している。例えば、ダンプツールを用いることで、
マットにコンパイルされる。このクラスファイルを構成
実行時のメモリの内容や実行中のプログラムの実行ファ
するバイトコードは高度な命令であるため、理解しやす
イルをダンプすることができる。これらを用いると、ソ
くなっている [5]。そのため、従来はクラスファイルをわ
フトウェアに施されたプロテクトの保護機構の箇所や保
かりにくいものにするという静的解析に対抗する議論が
護のメカニズムの特定が行える。これにより、保護機構
多かった。その一方で、動的解析に対抗する技術につい
の改ざんを容易にしてしまうため、プロテクトが無効化
ては議論があまりされてこなかった。
される可能性の増加へと繋がってしまう。これらに対抗
本稿では、動的解析に対抗するため、Java プログラム
するために、今日、様々なソフトウェア難読化手法が提
を対象に、引数順序を入れ替えてメソッド A の呼び出
案されている。ソフトウェア難読化とは、プログラムを
∗
†
‡
しをメソッド B の呼び出しに誤認させる手法に焦点を
当てる。この手法は、福田らにより、Java 言語を対象に
京都産業大学コンピュータ理工学部, 京都市北区上賀茂本山 , Motoyama, Kamigamo, Kita-ku, Kyoto-shi, Kyoto
京都産業大学大学院 先端情報学研究科, 京都市北区上賀茂本山 ,
Motoyama, Kamigamo, Kita-ku, Kyoto-shi, Kyoto
京都産業大学コンピュータ理工学部, 京都市北区上賀茂本山, Motoyama, Kamigamo, Kita-ku, Kyoto-shi, Kyoto
静的解析に対して提案・実装されている [4, 9]。今回は
この手法をプログラムの実行時に行うことで、動的解析
に対する技術として提案・実装する。Java 言語では、ク
1
ラスファイルはロード後に一切変更が不可能で、これを
動的解析への対抗手段を増やすために、動的難読化の手
行おうとすると JVM の変更が必要である。そのため、
法を提案する。
移植性を考慮すると現実的ではない。しかし、Java 5 か
提案手法
ら Instrumentation 機構が導入され、ロード後もクラス
3
ファイルの変更が可能となった。この機能を難読化に適
3.1
用しようと、玉田らが Java 言語で動的多様化を適用す
難読化とは、プログラムを意図的に理解しづらい等価
る手法を提案している [11, 13]。
なプログラムに変換することによって、不正解析やクラッ
玉田らの手法と福田らの手法を基に、動的に引数順序
キングを妨害する技術のことである。難読化の手法の例
を入れ替える手法を述べる。そして、プロトタイプツー
として、プログラム中の関数名や変数名を意味のない文
ルを作成し、使用時の実行時間の測定を行う。また、保
字列に置き換えることで理解しづらくさせる名前難読化
護機構を発見されてしまうと、保護機構が改ざんされて
や、ループを複雑にしたりダミー命令の追加するコント
しまう恐れがある。そのため、保護機構の発見のしにく
ロールフロー難読化が挙げられる [6]。これらの難読化
さを評価するために、難読化後のプログラムの不自然さ
はいずれもソフトウェア内部の情報の一部を、人間が理
を評価した。最後に、提案手法が動的解析に対してどの
解しづらい複雑な形に変換して理解を妨げるようとして
程度保護ができるかを評価するために、クラスファイル
いる。
をダンプするプログラムを用いて提案手法の攻撃耐性を
難読化とは、次のように定義される。難読化対象のプ
評価した。
2
ソフトウェア難読化
ログラムを p とし、p に含まれる秘密情報を X とする。
p の中の X を隠ぺいする難読化を適用した結果を p′ と
したとき、以下の条件を満たす [4, 9]。
関連研究
本稿で提案する手法では、動的多様化を用いる。動的
条件 1 p に任意の入力 I を与えたときの出力を result(p, I)
多様化とは、プログラムの意味や入出力の関係を保持し
たまま、実行ごとに少しずつ異なる挙動を行うようプロ
としたとき、p′ の出力は result(p, I) = result(p′ , I)
グラムを動的に変更するものである [11]。動的多様化技
となる。
術を用いた難読化手法として、神崎らによって提案され
条件 2 p から X を取り出すコストを cost(p, X) とした
た命令のカムフラージュによる手法が挙げられる [7]。こ
とき、cost(p, X) < cost(p′ , X) となる。
の手法は、まずプログラム中に任意の命令をダミー命令
に書き換えておく。そして、ダミー命令が実行される直
条件 1 は、難読化前後のプログラムにそれぞれ同一の
前に元の命令に戻すようにプログラムが自分自身を書き
入力を与えたとき、出力が変わらないことを意味する。
換える。元の命令を実行した後に、再びダミー命令に書
つまり、難読化により変換されたプログラムは、難読化
き換えるという手法である。この手法は主にアセンブラ
適用前のプログラムと等価であることを示している。条
を対象にしており、そのまま適用するのは難しい。これ
件 2 は、難読化後のプログラムの方が情報を取り出すこ
は、従来の Java 言語では、クラスファイルはロード後
とが困難になることを意味する。
に一切の変更が不可能であったためである。つまり、実
難読化は必ずしもプログラム p のソースコードに適
行時のバイトコードの書き換えが不可能だということで
用されるわけではない。一般に保護対象のプログラムの
ある。しかし、Java 5 から Instrumentation 機構が導入
ソースコードは外部に公開されないため、バイトコード
されたことで実行時のバイトコードの書き換えが可能に
のような実行コードに適用されることが多いからである。
なった。玉田らはこの機構を難読化に適用するために、
キーアイデア
Java 言語で動的多様化を適用する手法を提案している
3.2
[6, 11, 13]。この提案された手法を利用した動的難読化
の手法として、類似命令列の畳み込みによる難読化が提
案されている [6, 13, 15]。
らによって Java 言語を対象に静的難読化として提案さ
メソッドの引数順序入れ替えの手法は、もともと福田
れた [4, 9]。福田らの手法は、確かに偽のコールフローグ
ラフを作成するため、静的解析に対しては堅牢である。
しかし、動的解析に対抗する技術についての議論はあ
まりされてこなかったため、今日までに提案されている
しかし一方で、動的解析に対しては脆弱であり、呼び出
動的難読化の手法はまだ少ない。手法が増えることで、
されたメソッドを辿れば本来のコールフローグラフが暴
動的解析への対抗手段が増えることになる。また、手法
露してしまう問題がある。そこで、本稿では、実行時に
が増えれば、適用範囲が重複しなければプログラムに複
動的にコールフローグラフを変更する方法を提案する。
数の難読化を併用できる。そのため、動的解析に対して
提案手法を使えば、呼び出されたメソッドを辿ったとし
堅牢な攻撃耐性を持つことができる。そこで、本稿では
ても本来のコールフローグラフが暴露せず、また、実行
2
途中でプログラム全体のコールフローグラフを取得した
2. オペランドを mt から mf に変更する。
としても、偽のコールフローグラフしか取得できないよ
3. 実行プログラムに対して、復帰ルーチンを持つフッ
うになる。
ク機構を追加する。
具体的には、実行するプログラムに事前に復帰ルーチ
ンを持つフック機構を埋め込み、プログラム実行時に本
4. mf が実行されるときに、フック機構でそのメソッ
来呼び出すメソッドとは異なるメソッドを呼び出すよう
ド呼び出し命令をフックする。
に偽装しておく。そして、その異なるメソッドが実行さ
5. 復帰ルーチンによって、Af を At に変換する。
れるときにそのメソッドをフック機構がフックし、復帰
ルーチンによって本来呼び出すメソッドが呼び出される
これにより、呼び出されるメソッドが mf から mt に変
ように戻すことで提案手法を実現する。
更されるため、本来のコールフローグラフとは異なった
3.3
コールフローグラフが作成される。
メソッドの引数順序入れ替えによる難読化
しかし、前述の通り、この難読化手法は静的解析に対
福田らが提案した手法に基づいて、メソッドの引数順
しては堅牢だが、動的解析に対しては、呼び出されたメ
序入れ替えによる難読化について説明する。
ソッドを辿れば本来のコールフローグラフが暴露してし
互いにオーバーロードの関係にある 2 つのメソッド mt ,
まうため、脆弱である。そのため、動的解析に対しても
mf があり、それぞれの実引数を At , Af とする。オー
堅牢性を保つには、この手法を動的に適用するよう拡張
バーロードの関係にあるメソッドが呼び出されるとき、
する必要がある。
どのメソッドが呼び出されるかはメソッド呼び出し命令
のオペランドとそのときのスタックの状態によって決ま
3.4
る。そして、特にスタックの状態に依存する。例えば、
動的への適用
メソッドの引数順序入れ替えによる難読化は静的難読
実引数 At , Af をそれぞれ At = {X, Y }, At = {Y , X}
化として提案されている。そこで、この難読化手法を動
としたとき、メソッド mt , mf の内どちらかが呼び出さ
的へと適用するために玉田らが提案した動的多様化技術
れるかを図 1 に示す。図 1 は、メソッド名が同じ場合で
[11, 13] を導入する。玉田らの提案手法を用いて、実行
時にバイトコードの再定義が可能となる。これにより、
も、呼び出されるメソッドはスタックの状態で決まるこ
とを示している。つまり,スタックの状態が {X, Y } の
実行時にメソッドの引数順序を入れ替えることができる
ときは引数が (X, Y ) である mt が呼び出され、{Y, X}
ため、呼び出すメソッドを動的に変更できる。つまり、
のときは引数が (Y, X) である mf が呼び出される。
動的にコールフローグラフを変更できる。
前述の通り、呼び出されるメソッドはメソッド呼び出
し命令のオペランドとそのときのスタックの状態によっ
ケーススタディ
4
て決まる。そのため、スタックの状態を変更するメソッ
4.1
ドの引数に合わせ、オペランドをオーバーロード関係に
実装
ある他方のメソッドに変更することで、呼び出されるメ
ここでは、第 3 章で述べた方法に従ってプロトタイプ
ソッドを変更できる。このことを利用することで引数順
ツールを作成する。まず、メソッドの引数順序入れ替え
序入れ替えによる難読化手法は本来呼び出すメソッドを
による難読化を実装するために、invokedynamic 命令と
mt 、偽のメソッドを mf としたとき、以下のような手順
で実現することができる。
java.lang.invoke.MethodHandles クラスの 2 つが必
要となる [4, 9]。そして、この難読化を動的に適用するよ
う拡張するためには動的多様化技術を導入する必要があ
1. mt の実行前に At をスタックに積む命令列を、Af
をスタックに積む命令列に変更する。
り、それには Instrumentation 機構を用いる [11]。これ
らを用いた上で、今回の実装では、バイトコード操作フ
レームワークである ASM[1] を使い、プロトタイプツー
スタックの状態 呼び出される
メソッド
Y!
X!
ルとして ICHIGO を実装した。
図 2 に難読化対象のクラスファイルの変換から実行時
の振る舞いまでの流れを示す。一般に、(a) ソースコー
mt (X,Y )
ドから (b) クラスファイルにコンパイルされ、(b) の状
態が配布される。提案手法では (b) からツールを用いて、
X!
Y!
前処理を行い、(c) の状態にし、これを実行する。そし
m f (Y, X )
て、(c) 前処理後のクラスファイルが実行されると、実
行時に自身を繰り返し再定義する。再定義の繰り返しに
図 1: スタックの状態と呼び出されるメソッド
3
1:public class Sample {
2: private String fileName = "prime_numbers.txt";
3: public void readNumbers()
4:
throws IOException {
5:
List<Integer> list = new ArrayList<>();
6:
File file = new File(fileName);
7:
BufferedReader br = new BufferedReader(
8:
new FileReader(file)
9:
);
10:
String line;
11:
while((line = br.readLine()) != null) {
12:
int primeNumber = Integer.valueOf(line);
13:
list.add(primeNumber);
14:
}
15: }
16: public static void main(String[] args)
17:
throws IOException {
18:
new Sample().readNumbers();
19: }
20:}
より、(d) 偽装されたクラスファイルと (e) 暴露された
クラスファイルの状態を繰り返す。
4.2
適用例
提案手法を用いて実装したプロトタイプツールを実際
のプログラムに適用する。適用対象のプログラムを図 3
に示す。
図 3 は図 2 の (b) クラスファイルに相当する。図 3 の
プログラムは、数値が書かれたファイルから文字列読み
込む。そして、文字列を数値に変換し、その数値をリス
トに格納するプログラムである。難読化対象のメソッド
を 12 行目の Integer クラスの valueOf(String) メソッ
ドとする。このメソッドは valueOf(String, int) のメ
ソッドとオーバーロードの関係にある。難読化を適用し
図 3: 適用対象のプログラム
て valueOf(String, int) メソッドを呼び出すように
偽装する。プロトタイプツールを用いて図 3 を難読化し
クを行っている。つまり、invokedynamic 命令とブート
たプログラムを図 4 に示す。
ストラップメソッドを用いることで、メソッド呼び出し
図 4 のプログラムは図 2 の (c) 前処理後のクラスファイ
のフックが実現できる。(e) の状態のブートストラップメ
ルと (d) 偽装されたクラスファイルに相当する。図 4 のプ
ソッドである図 5 には復帰ルーチンが定義されており、
ログラムでは、偽装が施されており、21 行目から 23 行目
復帰ルーチンを実行することで本来呼び出すメソッドで
で valueOf(String, int) を呼び出すようにしている。
ある valueOf(String) が呼び出される。そして、25 行
そして、20 行目で書き換えを行い、valueOf(String)
目の書き換えによって再定義が行われて、(e) の状態が
を呼び出すようにする。そのため、20 行目の書き換え
(d) の状態に戻る。
が実行された状態は図 2 の (e) 暴露されたクラスファイ
評価
5
ルに相当する。20 行目の書き換えが実行されると、図
4 のプログラム中の 3 行目から 10 行目のメソッドが図
5 のように書き換わる。これは、図 2 における (d) の
能を評価するため、評価実験を行う。実験ではパフォー
状態が再定義によって、(e) の状態になる部分に相当す
マンス、ステルシネス、攻撃耐性のそれぞれについて評
る。図 4 のプログラム中の 3 行目から 10 行目のメソッ
価する。パフォーマンスとステルシネスの評価には、図
ドと図 5 のメソッドはブートストラップメソッドと呼ば
れる特殊なメソッドである。また、20 行目の書き換え
2 の (b) と (c) の状態のクラスファイルを用いる。攻撃
耐性の評価には、図 2 の (d) と (e) の状態のクラスファ
では、valueOf(String, int) を呼び出す際に実行され
イルを用いる。難読化対象のメソッドを Integer クラ
るメソッド呼び出し命令を invokedynamic 命令に変換
スの parseInt(String) メソッドとし、偽のメソッドを
する。invokedynamic 命令は初回実行時に対応するブー
parseInt(String, int) とする。実行環境は MacBook
トストラップメソッドを呼び出すため、このメソッドを
Air, OS X Mavericks, CPU は Intel Core i7 1.7GHz, メ
モリは 8GB である。
提案手法を用いて実装したプロトタイプツールの性
プログラム中に定義しておく必要がある。定義しておく
ことで、invokedynamic 命令は valueOf(String, int)
5.1
を呼び出す前にブートストラップメソッドを呼び出す。
これは、invokedynamic 命令がメソッド呼び出しのフッ
パフォーマンスの評価
実装したプロトタイプツールの性能評価のために、実
行時間を測定した。図 4 のプログラムでは、19 行目か
コンパイル
する
プロトタイプ
ツールを適用
する
(a) ソースコード (b) クラスファイル
実行する
(c) 前処理後の
クラスファイル
再定義する
実行環境
ら 26 行目でループが行われており、ループ 1 回ごとに
2 回の書き換えが行われている。そこで、書き換え回数
が 500, 1000, 1500, 2000, 2500, 3000 となるようなルー
再定義する
(d) 偽装された
(e) 暴露された
クラスファイル
クラスファイル
プ回数で図 2 の (b) と (c) の実行時間を測定する。それ
ぞれループ回数についての実行時間を 10 回ずつ測定し、
その結果の平均を測定結果とする。難読化前後の実行時
図 2: 難読化対象のクラスファイルの変換から実行時の
間と遅延倍率を示した結果を表 1 に示す。
振る舞いまでの流れ
表 1 より、書き換え回数 500 毎に 2 秒から 3 秒程度の
4
表 1: 実行時間の測定結果と遅延倍率
ループ回数
書き換え回数
難読化前(ms)
難読化後(ms)
遅延倍率(難読化後/難読化前)
250
500
2,003
2,630,783
1,313.49
500
1,000
2,640
4,718,174
1,787.46
1:public class Sample {
2: private String fileName = "prime_numbers.txt";
3: public static CallSite bsm(Lookup lookup,
4:
String name, MethodType methodType)
5:
throws Throwable {
6:
MethodHandle mh = lookup.findStatic(
7:
Integer.class, "valueOf", methodType
8: );
9:
return new MutableCallSite(mh);
10: }
11: public void readPrimeNumbers()
12:
throws IOException {
13:
List<Integer> list = new ArrayList<>();
14:
File file = new File(fileName);
15:
BufferedReader br = new BufferedReader(
16:
new FileReader(file)
17:
);
18:
String line;
19:
while((line = br.readLine()) != null) {
20:
Premain.getInstance().update();
21:
int primeNumber = Integer.valueOf(
22:
line, 16
23:
);
24:
list.add(primeNumber);
25:
Premain.getInstance().update();
26:
}
27: }
28: pubic static void main(String[] args)
29:
throws IOException {
30:
new Sample().readPrimeNumbers();
31: }
32:}
750
1,500
3,032
6,826,245
2,251.18
1,000
2,000
3,516
9,635,786
2,740.24
1,250
2,500
3,859
11,041,722
2,861.51
1,500
3,000
4,325
13,635,526
3,152.87
public static CallSite bsm(Lookup lookup,
String name, MethodType methodType)
throws Throwable {
MethodType type = MethodType.methodType(
Integer.class, String.class
);
MethodHandle mh = lookup.findStatic(
Integer.class, "valueOf", type
);
MethodHandle anotherMH =
MethodHandles.dropArguments(
mh, 1, int.class
);
return new MutableCallSite(anotherMH);
}
図 5: 暴露されたクラスファイルのブートストラップメ
ソッド
発見されやすくなる。このステルシネスの評価手法は神
崎らによって提案されている [12]。また、神崎らの評価
手法をオブジェクト指向言語向けに拡張した評価手法も
提案されている [14]。[14] では、平均分岐数を表すパー
プレキシティ(perplexity)という指標を用いており、本
研究では、このパープレキシティをプログラムの不自然
さの指標として利用する。
パープレキシティを計算するには、バイトコードをメ
図 4: 難読化後のプログラムの疑似コード
ソッドごとのオペコード列に変換したコーパスを構築
する必要がある。そこで、今回は、統合開発環境である
遅延が生じていることがわかる。このことから、難読化
Eclipse[3] のプラグイン jar ファイル 751 個からコーパ
の際に選択するメソッドは呼び出し回数の少ないメソッ
スを構築した。図 2 の (b) と (c) の状態でのプログラム
ドが望ましい。また、ユーザからの入力が必要なソフ
の不自然さの測定結果と、代表的な難読化手法を図 3 の
トウェアのような厳しい応答速度が要求されないソフト
プログラムに適用して不自然さを測定した結果を表した
ウェアには、提案手法は適していると考えられる。一方
ものを図 6 に表す。図 6 では、左端のバーが (b) の状態
で、リアルタイム処理が求められるプログラムに対して
のパープレキシティを、左から 2 番目のバーが提案手法
は、遅延が大きいため、提案手法を適用するには何らか
のパープレキシティを表している。それ以降のバーは、
の対策を要する。
既存の難読化手法のパープレキシティを表している。
5.2
図 6 より、提案手法の不自然さは難読化前後で微増し
ステルシネスの評価
攻撃者に保護機構が発見されると保護機構が改ざんさ
れてしまう恐れがあるため、保護機構の発見のしにくさ
(ステルシネス)を評価する。プログラムに対して保護
機構を施したとき、追加や変更を行ったコードが不自然
であればあるほどステルシネスが低くなる。つまり、攻
撃者に保護機構が発見されやすくなるということであ
る。この不自然なコードというのは、アセンブリコード
としてもっともらしくないコードのことを指す。不自然
なコードはステルシネスが低く、攻撃者にとって保護さ
図 6: 不自然さの測定結果
れていないコードと区別がつきやすいため、保護機構が
5
ている。この増加量は、他の難読化手法よりも小さい。
コールフローグラフを変更する方法を提案した。提案手
このことから、提案手法は他の難読化と比較して不自然
法を用いてプロトタイプツールを作成し、パフォーマン
さが低いため、ステルシネスが高いと言える。
ス、ステルシネス、攻撃耐性の評価を行った。パフォー
5.3
マンスの評価の結果、実行時間は書き換え回数 500 毎に
攻撃耐性の評価
撃耐性を評価する。今回は、Javassist [8] を用いた実行
2 秒から 3 秒程度の遅延が確認できた。この結果より、
厳しい応答速度が要求されないソフトウェアに適してい
ると考えられる。提案手法のステルシネスの評価の結果、
時のクラスファイルをダンプするプログラムを用いる。
難読化前後で不自然さの変化は小さく、他の難読化手法
提案手法の攻撃に対する堅牢性を評価するために、攻
プログラムが再定義された後である図 2 の (d) と (e)
と比べても不自然さの変化は小さかった。この結果より、
の状態のクラスファイルを先ほどのダンプするプログラ
提案手法によるステルシネスの減少は小さいため、難読
ムを用いてダンプした。ダンプした結果、ダンプしたプ
化を適用されていないコードとの区別がつきにくいこと
ログラムはどちらも図 2 の (b) の状態のクラスファイル
が確認できた。攻撃耐性の評価の結果、クラスファイル
と同じであることが確認できた。(e) の暴露されたクラ
をダンプするプログラムによる実行時のクラスファイル
スファイルがダンプされなかったため、提案手法はクラ
のダンプを行い、図 2 の (b) の状態のクラスファイルが
スファイルをダンプするツールに対して攻撃耐性がある
ダンプされた。この結果より、(e) の暴露されたクラス
と言える。
ファイルがダンプされなかったため、提案手法はクラス
6
ファイルをダンプするプログラムに対して攻撃耐性があ
議論
ることが確認できた。
提案手法を適用したプログラムは、特殊なコードを含
今後の課題として、動的コールフローグラフを作成す
むプログラムとなる。これは、自己書き換えを行うため
るツールに対する攻撃耐性を評価し、実際に動的コール
に Instrumentation 機構を用いているからである。その
フローグラフを偽装できるかを確認する必要がある。
ため、適用部分が特定されやすく、その部分を削除され
謝辞
てしまう可能性がある。しかし、提案手法は適用したプ
ログラムが実行される前に偽のメソッドを呼び出すよう
本研究の一部は,JSPS 科研費 若手研究 (B) 25730087
に書き換えを行っている。そのため、自己書き換えを行っ
の助成を受けて行われた.
ているコードが削除されると、復帰ルーチンは実行され
参考文献
ない。これにより、本来呼び出すメソッドではなく偽の
メソッドが実行される。その結果、プログラムは意図通
[1] Eric Bruneton: ASM 4.0 A Java bytecode
engineering library, http://download.forge.
りの動作を行えなくなる。
懸念すべき点として、提案手法を適用したプログラ
objectweb.org/asm/asm4-guide.pdf.
ムには、偽のメソッドを本来呼び出すメソッドに変更す
るためにブートストラップメソッドを定義する必要があ
[2] Christian Collberg and Jasvir Nagra: Surrepti-
る。ブートストラップメソッドは invokedynamic 命令の
tious Software Obfuscation, Watermarking, and
Tamperproofing for Software Protection, AddisonWesley (2009).
初回実行時にのみ JVM から呼び出される [4, 9]。つま
り、ブートストラップメソッドを定義したプログラムか
ら能動的に呼び出す必要がない。このように、ブートス
[3] The Eclipse Foundation: Eclipse - The Eclipse
Foundation open source community website.
トラップメソッドはかなり特殊なメソッドであるため、攻
撃者の目につきやすくなってしまう。また、ブートスト
http://www.eclipse.org/
2014/11/16).
ラップメソッドは本手法における復帰ルーチンであるた
め、メソッドの中身を解析されると本来呼び出すメソッ
ドが看破されてしまう可能性がある。対策として、動的
Access:
[4] Kazumasa Fukuda and Haruaki Tamada:
名前解決による名前難読化 [10] のような API ライブラ
An
Obfuscation Method to Build a Fake Call
Flow Graph by Hooking Method Calls, 14th
リ名を隠ぺいする難読化を併用し、ブートストラップメ
ソッド内の中身を隠ぺいすることが考えられる。
7
(Last
ACIS International Conference on Software
Engineering, Artificial Intelligence, Networking and Parallel/Distributed Computing ([SNPD
まとめ
2014](http://www.acisinternational.org/snpd2014/)),
pp. CD–ROM (2014). Las Vegas, U.S.A.
本稿では、メソッドの引数順序入れ替えによる難読化
手法を動的に適用するように拡張することで、動的に
6
[15] 西岡隆司, 山内寛己, 門田暁人, 中村匡秀, 松本健一:
類似した命令列の畳み込みによるプログラムの耐タ
[5] Tim Lindholm, Frank Yellin, Gilad Bracha and
Alex Buckley: Java Virtual Machine Specification
ンパ性の向上, 情報処理学会研究報告ソフトウェア
Java SE 7 Edition, Addison-Wesley (2013).
工学 (SE)2007, Vol. 33, pp. 167–174 (2007).
[6] Tetsuya Ohdo, Haruaki Tamada, Yuichiro Kanzaki and Akito Monden: An Instruction Folding
Method to Prevent Reverse Engineering in Java
Platform, In Proc. 13th ACIS International Conference on Software Engineering, Artificial Intelligence, Networking and Parallel/Distributed Computing (SNPD 2013), pp. 517–522 (2013).
[7] Akito Monden Yuichiro Kanzaki, Masahide Nakamura and Ken ichi Matsumoto: A Software Protection Method Based on Instruction Camouflage,
Electronics and Communications in Japan, Part
3 , Vol. 89, No. 1, pp. 47–59 (2006).
[8] 千 葉 滋:
Javassist Home Page,
//www.csg.is.titech.ac.jp/~chiba/
http:
javassist/index.html.
[9] 福田収真, 玉田春昭: メソッド呼び出し関係隠ぺいの
ための引数順序の入れ替えによる難読化, 2014 年暗
号と情報セキュリティシンポジウム (SCIS 2014)(講
演番号 2D2-3) (2014).
[10] 玉田春昭, 中村匡秀, 門田暁人, 松本健一: API ラ
イブラリ名隠ぺいのための動的名前解決を用いた
名前難読化, 電子情報通信学会論文誌, Vol. J90-D,
No. 10, pp. 2723–2735 (2007).
[11] 玉田春昭, 神崎雄一郎, 門田暁人: Java 言語を対象
とした実行時多様化の試み, 2012 年暗号と情報セ
キュリティシンポジウム (SCIS 2012) 予稿集 CD-
ROM(講演番号 4E2-3) (2012).
[12] 神崎雄一郎, 尾上栄浩, 門田暁人: コードの「不自
然さ」に基づくソフトウェア保護機構のステルシネ
ス評価, 情報処理学会論文誌, Vol. 55, No. 2, pp.
1005–1015 (2014).
[13] 大堂哲也, 玉田春昭: Java を対象とした畳み込み
手法による耐タンパ化の試み, 2013 年暗号と情報
セキュリティシンポジウム (SCIS 2013)(講演番号
2C4-3) (2013).
[14] 大滝隆貴, 大堂哲也, 神崎雄一郎, 門田暁人: Java バ
イトコード命令のオペコード、オペランドを用いた
難読化手法のステルシネス評価, 2014 年暗号と情報
セキュリティシンポジウム (SCIS 2014)(講演番号
2D2-2) (2014).
7