Posts 난독화 기술 : Opaque predicate
Post
Cancel

난독화 기술 : Opaque predicate

- Opaque predicate란?

한 방향으로 실행되는 조건문을 만들고, 실행되지 않는 부분에 쓰레기 코드를 삽입하는 대표적인 난독화 방법 중 하나이다. 이는 프로그램 일부를 최적화하는 것을 어렵게 하고, 제어 흐름을 복잡하게 만듦으로써 프로그램 분석을 방해할 수 있다.12

3가지 유형으로 구분할 수 있다.3

1. Invariant Opaque Predicates

x^2^>0와 같이 어떠한 x가 들어오더라도 만족하는 식을 조건으로 작성하는 방법이다. 이는 fuzzing(임의의 데이터를 input으로 넣어보면서 프로그램의 작동을 확인하는 방법)을 통해 어떤 결과가 나오지 않는지를 확인할 수 있다.

2. Contextual Opaque Predicates

어떠한 전제 조건에서는 항상 같은 값을 낼 수 있는 조건을 조건문에 작성하는 방법. 전제 조건의 값만 알아도 어떤 흐름을 타게 되는지 알 수 있다.

예를 들면, 다음과 같은 그래프에서는 x>1일 경우 항상 양수이므로, x>1을 전제 조건으로 주는 것과 같다.

graph

3. Dynamic Opaque Predicate

실행할 때마다 조건문의 흐름을 타는 방향은 다르지만, 결과는 항상 같게 되는 방법이다. Correlated와 Adjacent의 두 가지 성질을 가진다.

- 적용 예시

1
2
3
4
5
6
int main(int a, int b)
{
  int result = 0;
  result = a + b;
  return result;
}

위의 코드는 두 parameter를 받아서 더하는 간단한 코드이다. 이를 앞에서 서술한 3가지의 방법으로 난독화 해 보았다.

1. Invariant Opaque Predicates

항상 같은 값이 나오는 조건을 a^2^>=0으로 두고, return을 제외한 stmt가 나올 때마다 난독화하였다.

1
2
3
4
5
6
7
8
9
10
11
int main(int a, int b)
{
  int result = 0;
  if (a * a >= 0) {
    result = a + b;
  } else {
    int temp = 0;
    result = temp;
  }
  return result;
}

2. Contextual Opaque Predicates

para>0일 경우는 para^2^>1이므로, stmt를 para^2^>1을 분기로 가지는 조건문으로 묶고 para>0인 (조건을 만족하는) para를 명시해 두었다.

1
2
3
4
5
6
7
8
9
10
11
12
int main(int a, int b)
{
  int result = 0;
  int para = 2;
  if (para * para >= 0) {
    result = a + b;
  } else {
    int temp = 0;
    result = temp;
  }
  return result;
}

3. Dynamic Opaque Predicate

para는 랜덤 값이 들어가도록 해 둔뒤, 첫 번째 조건문에서는 para>0, 두 번째 조건문에서는 para<=0을 조건으로 둔다. 첫 번째와 두번째는 결국 true→false 또는 false→true일 수 밖에 없는데, 이 두 경우의 output이 같을 수 있도록 한다. true에서 result–;를 했으면 false에서는 result++;를 넣어주는 방식이다. 이는 앞의 두 방식과는 다르게, 종료하기 return문 전에 연산을 수행할 수 있게 하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main(int a, int b)
{
  int result = 0;
  result = a + b;
  int para = rand() % 9;
  if (para * para >= 0) {
    result--;
  } else {
    result++;
  }
  if (para * para < 0) {
    result++;
  } else {
    result--;
  }
  return result;
}

전부 코드를 읽고 단순 변환하는 단계에서 바꾸어 보았는데, 직접 바꿔준다는 느낌이 많이 들어서 변환이 이루어지는 단계가 좀더 이르면 좋을 것 같다. 예를 들어 파일을 읽고 따로 구조만 파악하여 바꿔준다는 느낌으로?

  1. Dongpeng Xu, Jiang Ming, Dinghao Wu. (n.d.). Generalized Dynamic Opaque Predicates: A New Control Flow Obfuscation Method(College of Information Sciences and Technology). The Pennsylvania State University, n.p.. 

  2. Genevi`eve Arboit. (n.d.). A Method for Watermarking Java Programs via Opaque Predicates(School of Computer Science, Crypto and Quantum Info Lab). McGill University, n.p.. 

  3. Jiang Ming, Dongpeng Xu, Li Wang, Dinghao Wu. (n.d.). LOOP: Logic-Oriented Opaque Predicate Detection in Obfuscated Binary Code(College of Information Sciences and Technology). The Pennsylvania State University, n.p.. 

This post is licensed under CC BY 4.0 by the author.

Contents

난독화 입문

1 - 난독화 적용 아이디어와 궁금했던 점