FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LLVMベースの難読化ツールoLLVMの調査 (2. 生成CFGの調査)

LLVMをベースにしたコードの難読化ツールとしてoLLVMというのがあるというのを知った。どういうものなのか少し見てみようと思う。

github.com

論文は以下で取得可能だ。

ieeexplore.ieee.org

  • Obfuscator-LLVM: Software Protection for the Masses

https://crypto.junod.info/spro15.pdf

oLLVMのビルドが終わったので動かしてみる。以下のサイトを見ながらやってみた。

blog.quarkslab.com

以下のプログラムをコンパイルしてみる。

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
}