본문 바로가기

Reversing

[Dreamhack] Binary & Analysis

리버스 엔지니어링 (Reverse Engineering) = 역공학 = 리버싱 🔍

 

프로그래밍 언어에는 고급 언어들과 어셈블리어, 기계어 등의 저급 언어들이 있다.

어셈블리어 → 기계어 (0, 1) by 어셈블러

컴파일) 고급 언어 (C, C++ ...) → 어셈블리어, 기계어by 컴파일러

 

* 인터프리팅 by 인터프린터

: 통역하듯이 그때 그때 작동함.

- 모든 언어가 컴파일을 필요로 하는 건 아니다! ex) Python, Javascript 

 

컴파일 과정

C로 작성된 코드 → 전처리 → 컴파일 → 어셈블 → 링크 → 바이너리로 번역됨

 

1. 전처리 (Preprocessing)

: 컴파일러가 소스 코드를 어셈블리어로 컴파일하기 전에, 필요한 형식으로 가공하는 과정

ex) 주석 제거, 매크로 치환 (#define), 파일 병합 (소스, 헤더 파일)

예제 코드
전처리

- add.i는 add.c를 전처리한 결과

- gcc의 -E 옵션을 사용하여 소스 코드의 전처리 결과 확인 가능

add.i (전처리 결과)

- 주석이었던 // return a+b가 사라지고,

- HI가 3으로 치환되고,

- add.h의 내용이 #include에 의해 병합되었음.

 

2. 컴파일

: 작성된 소스 코드를 어셈블리어로 번역하는 과정

- 소스 코드의 문법을 검사함. 문법적 오류가 있다면 에러를 출력

- gcc의 -S 옵션

컴파일
add.S (소스 코드를 어셈블리 코드로 컴파일한 결과)

 

3. 어셈블

: 컴파일로 생성된 어셈블리어 코드를 ELF형식의 목적 파일(Object file)로 변환하는 과정

* ELF : 리눅스의 실행파일 형식

* 윈도우에서 어셈블한다면 목적 파일은 PE형식을 갖게 됨

- 목적 파일로 변환되고 나면 어셈블리 코드가 기계어로 번역되므로 더이상 사람이 해석하기 어려워짐

- gcc의 -c 옵션

add.S를 목적 파일로 변환한 결과 파일을 16진수로 출력한 것

 

4. 링크

: 여러 목적 파일들을 연결하여 실행 가능한 바이너리로 만드는 과정

링크가 필요한 이유 @.@

 

디스어셈블

기계어 → 어셈블리어로 재번역하는 과정. 즉, 어셈블의 역과정.

 

디컴파일

: 어셈블리어보다 고급 언어로 바이너리를 번역하는 과정

- 일반적으로 바이너리의 소스 코드와 동일한 코드를 생성하지는 못함

- 디스어셈블러보다 더 분석 효율을 높여줌. 따라서 디컴파일러를 사용하는 것이 유리함.

- 디컴파일러 ex) Hex Rays, Ghidra

 

요약 📝

프로그램 : 컴퓨터가 실행해야 할 명령어의 집합, 바이너리라고도 불림

전처리 : 소스 코드가 컴파일에 필요한 형식으로 가공되는 과정

컴파일 : 소스 코드를 어셈블리어로 번역하는 과정

어셈블 : 어셈블리 코드를 기계어로 번역하고, 이 코드를 담고 있는 실행 가능한 형식의 목적 파일을 만드는 과정

링크 : 여러 개의 목적 파일을 하나로 묶고, 필요한 라이브러리와 연결해주는 과정

디스어셈블 : 바이너리를 어셈블리어로 번역하는 과정

디컴파일 : 바이너리를 고급 언어로 번역하는 과정

 

 

 


 

 

 

소프트웨어의 분석 기법

1. 정적 분석 (Static Analysis)

2. 동적 분석 (Dynamic Analysis)

 

정적 분석 🔍

: 프로그램을 실행시키지 않고 분석하는 방법

 

장점 1) 프로그램의 전체구조를 파악하기 쉽다.

장점 2) 분석 환경의 제약에서도 비교적 자유롭다.

장점 3) 바이러스와 같은 악성 프로그램의 위협으로부터 안전하다.

 

단점 1) 프로그램에 난독화가 적용되면 분석이 매우 어려워진다.

- 개발자가 자신의 소프트웨어를 리버스 엔지니어링으로부터 보호하기 위해 난독화 기법을 적용함

→ 프로그램 코드가 심하게 변형돼서 이를 읽고, 실행 흐름 파악하기가 어려워짐

- 많은 상용 난독화 서비스들을 무력화하는 방법은 알려지지 않았음

단점 2) 정적 분석만으로는 다양한 동적 요소를 고려하기 어려움.

 

대표적인 도구 : IDA

좌측 - 프로그램을 구성하는 여러 함수와 프로그램과 관련된 각종 정보들

가운데 - 프로그램의 어셈블리 코드

우측 - 디컴파일된 코드

이외에도, 문자열이나 함수를 어디에서 사용하는지 보여주는 상호 참조 기능이나 함수 실행 흐름을 보기 쉽게 해주는 제어 흐름 그래프 등을 제공한다.

 

동적 분석 🔍

: 프로그램을 실행시키면서 분석하는 방법

 

장점 1) 코드를 자세히 분석해보지 않고도 프로그램의 개략적인 동작을 파악할 수 있음

단점 1) 분석 환경을 구축하기 어려울 수 있음.

- 다른 환경의 프로그램들을 동적 분석할 때에는 가상 머신을 구축하거나 프로그램을 실행할 수 있는 장치를 구매해야 하는데, 이 과정이 대상에 따라 매우 번거롭고 어려울 수 있음

 

* 안티 디버깅 (Anti Debugging)

: 동적 분석의 일종인 디버깅을 방해하는 기법

 

x64dbg

: 윈도우의 대표적인 동적 분석 도구로, 디버거 중 하나

 

디버거

: 프로그램의 버그를 찾아내고 제거하기 위해 사용되는 도구로, 실행 중인 어셈블리 코드, CPU의 레지스터 상태, 메모리와 스택의 값을 확인하며 분석을 진행할 수 있음

 

컴파일 할 코드

1) 현재 코드는 0x31337이라는 상숫값을 스택에 저장하고 있음. int n = 0x31337에 대응됨

2) 1)의 코드를 실행한 직후, 오른쪽 아래를 보면 스택에 0x31337이 저장된 것을 확인할 수 있음

3) printf 함수를 호출함. 오른쪽 위의 레지스터 영역을 보면, rcx에 Hello World 0x%x\n 문자열이, rdx에 0x31337이 저장된 것을 확인할 수 있음.

4) 3)의 코드를 실행한 직후, 프로그램을 보면, Hello World 0x31337이 출력된 것을 확인할 수 있음.

→ 이처럼 동적 분석은 프로그램을 실제로 실행하며 시스템의 변화를 관찰하는 것이 특징임. 함수 실행 시, 어떤 인자가 함수로 전달되며, 그 때의 메모리 상태는 어떠한지 등을 직관적으로 확인 가능함.

 

 

 

참고

https://dreamhack.io/lecture/roadmaps/4

 

Reverse Engineering

리버스 엔지니어링을 공부하기 위한 로드맵입니다.

dreamhack.io

 

'Reversing' 카테고리의 다른 글

VMware Pro / Windows XP 설치  (0) 2022.04.09
crackme #1 / 리틀 엔디안 / PEview  (0) 2022.03.26
Visual Studio 2019 / Immunity Debugger / 문자열 패치  (0) 2022.03.11
[Dreamhack] x86 Assembly  (0) 2022.03.05
[Dreamhack] Computer Science  (0) 2022.02.28