LLVMをベースにしたコードの難読化ツールとしてoLLVMというのがあるというのを知った。どういうものなのか少し見てみようと思う。
論文は以下で取得可能だ。
- Obfuscator-LLVM: Software Protection for the Masses
https://crypto.junod.info/spro15.pdf
oLLVMのビルドが終わったので動かしてみる。以下のサイトを見ながらやってみた。
以下のプログラムをコンパイルしてみる。
unsigned int target_function(unsigned int n) { unsigned int mod = n % 4; unsigned int result = 0; if (mod == 0) result = (n | 0xBAAAD0BF) * (2 ^ n); else if (mod == 1) result = (n & 0xBAAAD0BF) * (3 + n); else if (mod == 2) result = (n ^ 0xBAAAD0BF) * (4 | n); else result = (n + 0xBAAAD0BF) * (5 & n); return result; }
難読化をしない場合のオプション:
../build/bin/clang target.c -emit-llvm -O3 -o target.bc -c ../build/bin/llvm-dis target.bc -o -
難読化をした場合のオプション:
../build/bin/clang target.c -emit-llvm -O3 -o target_flat.bc -c -mllvm -fla ../build/bin/llvm-dis target_flat.bc -o -
確かに難読化した方が、CFGが良く分からないように拡張されている。どういう対応になっているのかは、これだけでは良く分からない。
; Function Attrs: norecurse nounwind uwtable define i32 @target_function(i32) local_unnamed_addr #0 { %2 = alloca i32, align 4 %3 = and i32 %0, 3 store i32 %3, i32* %2, align 4 %4 = or i32 %0, -1163210561 %5 = xor i32 %0, 2 %6 = mul i32 %4, %5 %7 = and i32 %0, -1163210561 %8 = add i32 %0, 3 %9 = mul i32 %7, %8 %10 = xor i32 %0, -1163210561 %11 = or i32 %0, 4 %12 = mul i32 %10, %11 %13 = add i32 %0, -1163210561 %14 = and i32 %0, 5 %15 = mul i32 %13, %14 br label %16 ; <label>:16: ; preds = %19, %1 %17 = phi i32 [ undef, %1 ], [ %20, %19 ] %18 = phi i32 [ 55288252, %1 ], [ %21, %19 ] switch i32 %18, label %19 [ i32 55288252, label %22 i32 -1124015321, label %26 i32 -877266683, label %27 i32 -1108936387, label %31 i32 -1480341395, label %32 i32 818845743, label %36 i32 -71238216, label %37 i32 -803031240, label %38 ] ; <label>:19: ; preds = %16, %37, %36, %32, %31, %27, %26, %22 %20 = phi i32 [ %15, %37 ], [ %12, %36 ], [ %17, %32 ], [ %9, %31 ], [ %17, %27 ], [ %6, %26 ], [ %17, %22 ], [ %17, %16 ] %21 = phi i32 [ -803031240, %37 ], [ -803031240, %36 ], [ %35, %32 ], [ -803031240, %31 ], [ %30, %27 ], [ -803031240, %26 ], [ %25, %22 ], [ %18, %16 ] br label %16 ; <label>:22: ; preds = %16 %23 = load volatile i32, i32* %2, align 4 %24 = icmp eq i32 %23, 0 %25 = select i1 %24, i32 -1124015321, i32 -877266683 br label %19 ; <label>:26: ; preds = %16 br label %19 ; <label>:27: ; preds = %16 %28 = load volatile i32, i32* %2, align 4 %29 = icmp eq i32 %28, 1 %30 = select i1 %29, i32 -1108936387, i32 -1480341395 br label %19 ; <label>:31: ; preds = %16 br label %19 ; <label>:32: ; preds = %16 %33 = load volatile i32, i32* %2, align 4 %34 = icmp eq i32 %33, 2 %35 = select i1 %34, i32 818845743, i32 -71238216 br label %19 ; <label>:36: ; preds = %16 br label %19 ; <label>:37: ; preds = %16 br label %19 ; <label>:38: ; preds = %16 ret i32 %17 }