特別研究Ⅰのメモ
今学期の研究でやったこと
・Javaバイトコードによる数式難読化
どんな難読化?
Javaのバイトコードレベルで計算式の部分を難読化
基本的にプログラム上で数式はスタックを二つ積んでいって算術演算子で一つに合体していきながら計算していく。
1 2 + = 3
上は逆ポーランド記法で表したけど様はこれと同じ。1と2のスタックを積んで+という演算子で合体すると3という一つのスタックになる
なので今回僕はスタックを最初に全部積んでから算術演算子で計算していく難読化を考えた
public class HelloWorld { public static void main(String[] args) { int i = 10; int j = 20; int k = 40; int l = (i + j) * k; System.out.println(l); } }
↓
コンパイル
↓
バイトコード
HelloWorld.class
public static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: bipush 20 5: istore_2 6: bipush 40 8: istore_3 9: iload_1 10: iload_2 11: iadd 12: iload_3 13: imul 14: istore 4 16: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 19: iload 4 21: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 24: return
これの
9: iload_1 10: iload_2 11: iadd 12: iload_3 13: imul
の部分を
9: iload_3 10: iload_1 11: iload_2 12: iadd 13: imul
上のようにして算術演算子であるi_add(+)やi_mul(*)が数字の入ったスタック(iload~)より後ろに来るようにする。
これがめっちゃ長い数式だと元の数式が何だったのか考えるのがとても困難になるけど今回提案した前の方に数字の入ったスタックにして後ろの方に算術演算子で固めるようにすると難読化前と難読化後の出力結果が異なる数式もある
例えば
(10+ 20) * (40 + 50)
上のような計算を逆ポーランド記法にすると
10 20 + 40 50 + *
こんな感じになるけどこれを
10 20 40 50|++*
こういうふうに数字と算術演算子を前後ろで分けて絶対数字の前に算術演算子来ない条件で計算するとどんだけ数字と演算子の順番変えても(10+20)*(40+50)と同じ計算結果にはならん
今回の研究で上のような数式も提案した難読化手法でできるようにしたかったけど結局できたのは上記のバイトコード(HelloWorld.class)のみ
改善策としては難読化前の出力結果を記憶しておいて難読化対象のバイトコードのみ前後ろに分けたりできたらどんな数式も難読化できそうやけど今のとこ実装方法が思いつかん
どんな数式にも自動で難読化できるようになるのが今後の課題
デコンパイリングJava ―逆解析技術とコードの難読化 (Art Of Reversing)
- 作者: Godfrey Nolan,松田晃一,小沼千絵,湯浅龍太
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/06/03
- メディア: 単行本(ソフトカバー)
- 購入: 5人 クリック: 204回
- この商品を含むブログ (20件) を見る