特別研究Ⅰのメモ

今学期の研究でやったこと
Javaバイトコードによる数式難読化



どんな難読化?
Javaバイトコードレベルで計算式の部分を難読化

基本的にプログラム上で数式はスタックを二つ積んでいって算術演算子で一つに合体していきながら計算していく。
1 2 + = 3
上は逆ポーランド記法で表したけど様はこれと同じ。1と2のスタックを積んで+という演算子で合体すると3という一つのスタックになる
なので今回僕はスタックを最初に全部積んでから算術演算子で計算していく難読化を考えた


ソースコード
HelloWorld.java

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)

デコンパイリングJava ―逆解析技術とコードの難読化 (Art Of Reversing)