study/논문

[논문] 단편화된 실행파일을 위한 데이터 구조 역공학 기법

lucykorea414 2023. 10. 1. 18:23
728x90

기본 정보

저자: 이종협

연도: 2012

게재처: 정보보호학회논문지

요약: 실행파일에 대한 정적인 분석을 통한 역공학 과정은 소프트웨어 보안에서 필수적인 단계이다. 역공학은 크게 소프트웨어가 사용하는 데이터 구조와 제어 구조에 대하여 수행된다. 특히 데이터 역공학은 소프트웨어를 이해하기 위해 필수적이지만 기존의 VSA기법은 단편화된 실행파일에 대한 한계를 가지고 있다. 본 논문에서는 동적인 영역할당을 통해 이러한 문제점을 해결하고 데이터 구조 역공학의 성능을 향상시킨다.

 

I. 서론 및 배경지식

단편화된 실행파일이란?

Fragmentation binary code → 함수가 여러개로 쪼개진 형태를 가지고 있는 파일

역공학(reverse engineering)이란?

실행파일만을 가지고 주어진 실행 파일이 어떠한 데이터 구조와 값을 사용하며 어떠한 작업을 수행하는지 알아내는 과정

→ 코드(고급언어)가 아니라 디스어셈블된 어셈블리어(저급언어)를 보고 파악하는 것

역공학의 종류

  • 동적분석 : 프로그램을 주어진 환경에서 실행시켜서 실행과정을 분석
  • 정적분석 : 프로그램의 실행 없이 프로그램 코드를 분석

동적분석 vs 정적분석

정적분석 과정

  • 프로그램의 데이터 구조에 대한 분석에서 시작
  • 변수들의 위치나 종류 파악 → 변수들의 구조 분석 → 실행 단계에서 스택/전역 변수 파악

∴ alias analysis를 기반으로 하는 value analysis 기법이 필요함

Alias Analysis

🔗위키피디아

  • “aliased”: 두개의 포인터가 같은 위치를 가르키고 있음
    • determines whether or not separate memory references point to the same area in memory
    • determines if a storage location may be accessed in more than one way
    • determines what variables in the program will be affected by a statement
  • 예시상식적으로는 i는 4라는 생각이 들지만, i가 나올 수 있는 값은 총 3가지 경우가 있다.
    1. p와 q는 alias 불가능 (can’t point to the same memory location)
      • 최적화 진행 가능
      • i = p.foo + 3i = 4
    2. p와 q는 무조건 alias
      • 최적화 진행 가능
      • i = p.foo + 3i = 5 ( ∵ (p.foo) + 3 = (q.foo) + 3 )
    3. 컴파일 시 p와 q가 alias 인지 아닌지 알 수 없음
      • 최적화를 진행할 수 없고 결과를 알기 위해서 전체 코드를 실행해야 함.

[예시]

p.foo = 1;
q.foo = 2;
i = p.foo + 3;

Value Analysis

  • value range analysis
  • tracks the range(intervals) of values that a numeric variable can take on at each point of a program’s execution
  • the resulting information can be used in optimizations such as redundancy elimination, dead code elimination, instruction selection 등… but also to improve program safety such as detection of buffer overruns

VSA와 한계점

  • VSA(Value-Set Analysis): 프로그램을 구성하는 각 영역(region)마다 SI로 표현되는 값을 하나식 가지는 value set을 구성하여 프로그램에서 사용하는 변수드을 찾아내는 작업 수행
  • 한계점: ‘정의되지 않은(undefined)’변수를 단순히 전범위 값([- ∞ , ∞])으로 치환 → 정확도가 크게 떨어짐

본 논문의 내용

정의되지 않은 값들의 변화를 유추하는 방법을 제공 → 프로그램의 데이터 구조 역공학 방법을 향상


II. 소프트웨어 역공학과 기존 기법의 문제점

2.1 소프트웨어 공학의 변수 탐색 및 복원

컴파일 과정

소스코드 → (컴파일) → 어셈블리 언어 → 인코딩한 기계어 코드

역공학 과정

기계어 → 어셈블리 언어

  • 소스코드가 주어지지 않았기 때문에 실행파일을 분석해야함
  • 실행파일에서는 소스코드에 있던 변수 정보는 사라지고 저수준의 메모리 접근 연산으로 단순화 ∴ 실제 데이터 구조를 찾을 수 없음
  • 메모리 접근 연산으로 변수 존재의 단서로 활용하여 변수 위치와 구조 유추

메모리 접근 연산

  • 상대주소를 가짐 → 스택 관련 포인터 레지스터인 EBP와 ESP의 연산으로 이루어짐(ex. EBP+8)
  • 상대주소이기도 하고, 레지스터를 두개나 사용하기 때문에 정확히 변수의 주소를 찾을 수 없음

 

2.2 Value-Set Analysis

SI 표현 방식

  • 숫자의 범위와 범위 내부의 간격값으로 구성
  • s[lb, ub] 형태
    • s: 간격값
    • lb: 최솟값
    • ub: 최댓값
  • 배열과 같이 표현이 되어 일정한 간격마다 변수가 존재하는 메모리 주소를 표현하는데 효과적임

VSA에서의 SI

  • VSA에서는 복수의 SI를 포함하는 value set을 사용함
  • 각 함수의 local stack frame을 독립적인 영역(region)으로 가정
    • 각 함수의 local stack마다 SI로 표현된 주소를 가르키는 독립된 값이 있음
  • value set = 독립된 값들의 집합
    • global 영역: 일반 상수/절대 주소
    • local 영역: 지역변수
  • 정의되지 않은(undefined) 값에 대해서는 1[-∞, ∞ ] = 이라는 값으로 초기화됨

  

 

2.3 VSA 문제점

VSA 분석

  • 복잡성 때문에 함수 단위로 나누어 분석 하는 경우, 정의되지 않은(undefined) 값들이 발생
    • ex) 함수의 인자(argument), malloc 함수의 return 값(context sensitive 분석이 적용되지 않을때) 등…
  • undefined 변수들을 VSA 에서는 다 초기화 해버림 → 이후의 변화를 확인 할 수 없음 → 메모리 접근에서 새로운 변수를 발견할 수 없음

undefined 변수 - 논문 예시

[어셈블리 분석]
  • %ebp+8에 있는 값(intArr의 내용)이 %eax 에 저장됨
  • %ebp+8에 위치한 변수에 11 이 저장됨
  • %eax+12에 위치한 변수에 %ebp-4(변수 vv)에 저장된 값이 할당 → (3)

C코드에서 intArr 라는 포인터로 함수 인자를 넘겨 받음

%ebp+8에 저장되어 있는 값이 정의되어 있지 않음(undefined, ∵ 다른 영역에서 정의되었기 때문)

→ 1[- ∞ , ∞]으로 초기화됨

→ +8, +12 연산 실행 불가능

→ intArr이 내포하는 변수들을 찾을 수 없음

undefined 변수 - 직접 따라해본 어셈블리 분석

[어셈블리 분석]

상대주소를 나타내기 위해 var_4와 arg_0이라는 변수가 쓰임

→ 스택에서 확인해보면 ? (undefined) 라는 값으로 확인됨

 


III. 제안 내용

VSA의 한계점 극복

  • VSA는 고정된 구조 → 정의되지 않은 값을 만나면 새로운 영역을 동적으로 할당하여 변화를 추적 가능
  • value set (독립적이라 변수 파악이 모호함) → 새로운 표현 방식 (값이 자신의 최근 영역만을 유지)

3.1 value의 정의

새로운 문법(syntax)

  • SI를 이용하긴 하지만 각 값은 하나의 영역에 대해서만 정의가 됨
    • Global 영역(global_val) : 일반 상수 / 절대주소를 이용하는 전역변수
    • 일반 영역(region_val) : 유일한 문자열(string)으로 구별
  • 모든 영역은 동적으로 할당됨

3.2 제안하는 기법의 동작 원리

분석 진행 과정

  • binary 상태의 대상 실행파일을 디스어셈블해서 어셈블리 상태로 변환
  • IL(Intermediate Language)로 변환 → 효율적인 분석을 위해
  • 정의된 규칙(statement, expression)에 의해 변수 값의 변화를 추적
  • 최종적으로 얻은 메모리 상태를 바탕으로 프로그램의 변수와 데이터 구조를 복원
✅ VSA에서는 하나의 변수여도 함수에서 다시 사용이 되면 초기화하여 stack에서 사용했는데 새로운 방법에서는 최종 메모리로 분석하니 같은 변수로 정상적으로 들어감!!

IL 분석 방법 기법

  • 어셈블리에서 사용하는 레지스터들과 임시적인 값으로 쓰는 값들은 ‘내부변수’에 저장하여 사용
  • 메모리도 큰 배열을 가진 하나의 ‘내부변수’로 다루어짐
  • 분석 후에는 메모리에 해당하는 내부변수의 인덱스 값들이 소스코드의 실제 변수가 있는 메모리 주소가 됨

IL의 규칙

  • IL에 대한 expression의 SI 연산은 VSA에 정의 된 규칙과 동일함
  • 동적인 영역 할당을 위해 추가적으로 필요한 규칙은 다음과 같음


IV. 구현 및 성능 평가

제안한 기법과 VSA 기법의 실험 결과 분석

  • Linux의 GNU Coreutil 8.4에 포함된 5개의 실행파일(cat, echo, kill, pwd, tty)을 대상으로 수행
  • 각 실행파일은 적법한 함수의 단위로 분리하여 총 375개의 함수에 대해 실험했음

<실험 결과>

  • 제안한 기법이 기존의 VSA에 비해 평균적으로 60.5개의 변수를 더 찾아낼 수 있었음
  • 찾아낸 변수들은 undefined 변수들이기 때문에 의미가 있음 (VSA로는 찾는게 불가능함)

 

728x90