リフレクションを用いた難読化

D3 玉田 春昭
mailto:harua‑t@is.naist.jp
ソフトウェア工学講座
リフレクションを用いた難読化
背景
‹内部に秘密データを持つソフトウェアが増加している
z解析されると困る
‹秘密データの例
zアルゴリズム
zDVD復号鍵
zライセンスチェック分岐
ソフトウェア
クラッカー
クラック
秘密データ
‹従来の難読化手法の問題点
zライブラリの呼出を隠せない
z変数の型を隠せない
z数値型の変数の値しか隠せない
‹難読化にリフレクションを利用することで従来手法の問題点を解決する
難読化手順と実施例
1.
2.
3.
4.
5.
6.
動的呼び出しを支援するクラス (DynamicCaller) を導入する
全てのメソッド,フィールドのアクセス権をpublicにする
メソッド呼び出しをDynamicCaller経由の動的呼び出しに変更する
フィールド参照・代入をDynamicCaller経由の動的参照・動的代入に変更する
全てのフィールド,ローカル変数の型をクラス階層のルートクラスに変更する
DynamicCallerに渡している文字列を暗号化する
public class ImageViewer extends javax.swing.JFrame{
private javax.swing.Icon icon;
public ImageViewer(String file){
setTitle(file);
getContentPane().add(new javax.swing.JLabel(
icon = new javax.swing.ImageIcon(file)));
pack();
}
}
MD5で難読化
public class ImageViewer extends javax.swing.JFrame{
public Object icon;
public ImageViewer(String file){
super();
DynamicCaller.invoke(this, new Object[] { file }, "5bfc6047de3903549175708dec7a7aa9", "51e19f59e833beaf5a38207229f438f7");
DynamicCaller.setField(this, DynamicCaller.invokeSpecial(new Object[] { file }, "2d43d42c97713a9e6c663405a3ae45b0"),
"5bfc6047de3903549175708dec7a7aa9", "baec6461b0d69dde1b861aefbe375d8a");
Object o1 = DynamicCaller.invokeSpecial(
new Object[] { DynamicCaller.getField(this, "5bfc6047de3903549175708dec7a7aa9", "baec6461b0d69dde1b861aefbe375d8a") },
"a51a85ee65e4f93ba3b462df9b215b62");
Object o2 = DynamicCaller.invoke(this, null, "5bfc6047de3903549175708dec7a7aa9", "9f1ee57da2ea52dd25e43df4ea773ab0");
DynamicCaller.invoke(o2, new Object[] { o1 }, "7379e4d292e149b58caddd4aa6a1e48f", "34ec78fcc91ffb1e54cd85e4a0924332");
DynamicCaller.invoke(this, null, "5bfc6047de3903549175708dec7a7aa9", "b484857901742afc9e9d4e9853596ce2");
}
}
D3 玉田 春昭
mailto:harua‑t@is.naist.jp
ソフトウェア工学講座
Birthmark
背景
‹
Birthmarkとは
ソフトウェアの盗用の事例は少なくない ‹ 盗用の疑いのあるプログラムを発見す
るための情報
z DivX コンバータ
z MAMEのライセンス違反,ネットげーせ ‹ プログラムの実行に不可欠な部分
ん
GImageView の盗作,PornView
Minute Mascot の盗作,Pocket
Mascot
z
z
z
予め情報を埋め込むことはない
‹ バースマークの種類
‹ プログラムの静的な特徴
‹ プログラム実行中の特徴
静的Birthmarkの例
動的Birthmarkの例
プログラムの静的解析により抽出できる特徴的な情報
プログラムの実行中に抽出できる特徴的な情報
public class HelloWorld extends Object{
private String string = "Hello World";
public void print(){
System.out.println(string);
}
}
Main.main()
HelloWorld()
Object()
:
HelloWorld.print()
PrintStream.println()
:
‹フィールド初期値Birthmark
‹メソッド呼出系列Birthmark
‹継承関係Birthmark
‹依存クラスBirthmark
HelloWorld(): 1
HelloWorld.print(): 1
Main.main(): 1
Object(): 10
PrintStream.println(): 5
‹実行系列Birthmark
‹実行頻度Birthmark
Birthmarkの性質
入力(動的Birthmark)
I
I
I
変換
プログラム
抽出法
Birthmark
p
p
f
保存性
f
f(p)
f(p)
=
静的Birthmark実験結果
p
≠
弁別性
f
f(p)
≠
p’
f(p’)
q
f(q)
動的Birthmark実験結果
1
ZKM
Smokescreen
jarg
CodeShield
0.8
保存性評価
平均: 93%
最小: 27%
最大: 100%
0.6
0.4
実行頻度Birthmark
弁別性評価
# of calls
100000
10000
1000
100
10
0.2
70
80
90
64
71
78
50
57
36
43
22
29
100
Seq. num. of API
STE Ext
STE2.00b7
TeaTime
Mp3tag
Tsuyutagu
127
60
113
50
120
40
99
30
106
20
85
10
92
0
8
1
0
15
1