리버스 엔지니어링(Reverse Engineering, RE:역공학)
장치나 시스템의 구조 분석을 통해 기술적인 원리를 발견하는 과정.
1# 대한민국 국가 법령에서의 리버스 엔지니어링
<저작권법> 제2조(정의) 이 법에서 사용하는 용어의 뜻은 다음과 같다. 34. "프로그램코드역분석"은 독립적으로 창작된 컴퓨터프로그램저작물과 다른 컴퓨터프로그램과의 호환에 필요한 정보를 얻기 위하여 컴퓨터프로그램저작물코드를 복제 또는 변환하는 것을 말한다.
제101조의4(프로그램코드역분석) ① 정당한 권한에 의하여 프로그램을 이용하는 자 또는 그의 허락을 받은 자는 호환에 필요한 정보를 쉽게 얻을 수 없고 그 획득이 불가피한 경우에는 해당 프로그램의 호환에 필요한 부분에 한하여 프로그램의 저작재산권자의 허락을 받지 아니하고 프로그램코드역분석을 할 수 있다. ② 제1항에 따른 프로그램코드역분석을 통하여 얻은 정보는 다음 각 호의 어느 하나에 해당하는 경우에는 이를 이용할 수 없다. 1. 호환 목적 외의 다른 목적을 위하여 이용하거나 제3자에게 제공하는 경우 2. 프로그램코드역분석의 대상이 되는 프로그램과 표현이 실질적으로 유사한 프로그램을 개발·제작·판매하거나 그 밖에 프로그램의 저작권을 침해하는 행위에 이용하는 경우
제104조의2(기술적 보호조치의 무력화 금지) ① 누구든지 정당한 권한 없이 고의 또는 과실로 제2조제28호가목의 기술적 보호조치를 제거·변경하거나 우회하는 등의 방법으로 무력화하여서는 아니 된다. 다만, 다음 각 호의 어느 하나에 해당하는 경우에는 그러하지 아니하다. 6. 정당한 권한을 가지고 프로그램을 사용하는 자가 다른 프로그램과의 호환을 위하여 필요한 범위에서 프로그램코드역분석을 하는 경우
2# 리버스 엔지니어링의 사례
패치(Patch): 파일이나 프로세스의 메모리 내용을 변경하는 작업 ex)Windows 업데이트 크랙(Crack): 패치와 같은 개념이지만, 비합법적이고 비도덕적인 경우 ex)저작권 침해행위(불법복제/사용 등)
3# 리버싱(분석) 방법
1. 정적분석 - 파일 실행 전에 얻을 수 있는 정보 분석
[관련 프로그램 : PE뷰어, WinHex 등]
2. 동적분석 - 파일 실행 상태에서 얻을수 있는 정보 분석
(상세분석) - 디버깅 툴을 이용해서 정확한 동작을 분석
[관련 프로그램 : Olly Debugger, IDA 등]
아키텍쳐
1# CPU(Center Processing Units)의 구조
2# 메모리 구조
3# 스택
후입선출(FILO: First-In Last-OUt / LIFO : Last-In First-Out) 구조 프로그램 실행 시 사용되며, Thread 단위로 생성 (시작 위치는 랜덤)
1. 용도 - 지역변수 저장, 임시데이터 백업, 함수 매개변수 전달, 함수 호출관련 정보, OS에서 필요할 때 사용
2. 종류 (Inter x86의 IA-32는 기본적으로 Full Descending Stack 사용)
-Empty Stack & Full Stack
<빈 공간을 Top으로 가진다> <마지막 데이터를 Top으로 가진다>
- Descending Stack & Ascending Stack
<주소가 4byte 씩 감소 / 윈도우에서 사용> <주소가 4byte 씩 증가 / 리눅스에서 사용>
4# 기본 프로그램 실행 레지스터 (Intel x86 CPU 기본구조인 IA-32 기준)
레지스터는 작은 데이터의 임시저장공간으로 연산처리 및 번지지정을 돕거나 컴퓨터의 장치들을 제어함.
1. General Purpose Register(범용 레지스터) - 32bit 8개
상수나 변수 저장에 사용.16bit CPU에서 사용되던 레지스터가 32bit로 확장되면서 E(Extended의 약자)가 앞에 붙음. 레지스터 크기별로 나눠서 사용 가능 ==> ex) 32bit EAX / 16bit AX / 8bit단위의 AH(Higher)와 AL(Lower)
레지스터 |
용도 |
비고 |
EAX |
산술·논리 연산, 함수 리턴 값 저장 등 | |
EBX |
간접 번지 지정, 부가적으로 필요할 때 사용 |
|
ECX |
반복 연산에 사용 |
|
EDX |
EAX와 함께 부가적으로 사용 |
|
ESI |
데이터 복사 전 주소 저장 (출발지 주소) |
|
EDI |
데이터를 복사할 주소 저장 (목적지 주소) |
|
EBP |
Stack의 제일 밑. 스택의 시작 주소 저장 |
|
ESP |
Stack의 제일 위. 스택의 끝 주소 저장 |
2. Instruction Pointer - 32bit 1개
레지스터 |
용도 |
비고 |
EIP |
다음 실행 명령의 주소 저장 (직접 변경 불가) |
3. Segment Register - 16bit 6개
페이징(Paging)기법으로 가상메모리를 실제물리메모리로 변경할 때 사용 (시작주소, 범위, 접근 권한 부여하여 메모리 보호)
세그먼트 메모리는 SDT(Segment Descriptor Table)에 기술되어 있고, 세그먼트 레지스터는 SDT의 주소를 가지고 있음
- SS(Stack Segment) : 메모리 상 스택 구현
- CS(Code Segment) :코드 세그먼트의 시작 주소
- DS(Data Segment) :데이터 세그먼트의 시작 주소
- ES(Data Segment) : 메모리 주소지정을 다루는 스트링 연산에 사용
- FS(Data Segment) : SEH(Structured Exception Handling), TEB(Thread Environment Block), PEB(Process Environment Block) 등의 주소계산 시 사용되며 고급 디버깅에서 사용됨
- GS(Data Segment) :
4. Program Status and Control Register - 32bit 1개 (Eflags)
각 bit마다 의미를 가지고 있고, 1(True) 또는 0(False) 값을 가짐 (● = 예약된 공간, 사용X)
● System Flag(시스템 플래그) ● Control Flag(컨트롤 플래그) ● Status Flag(상태 플래그)
● ID(ID Flag)
● VIP(Virtual Interrupt Pending)
● VIF(Virtual Interrupt Flag)
● AC(Alignment Check)
● VM(Virtual-8086 Mode)
● RF(Resume Flag)
● NT(Nested Task)
● IOPL(I/O Privilege Level)
● OF(Overflow Flag) : 부호 있는 수의 오버플로가 발생했을 때, MSB(Most Significant Bit)가 변경되었을 때 1로 세팅
● DF(Direction Flag)
● IF(Interrupt Enable Flag)
● TF(Trap Flag) : 프로세서가 단일스텝모드(single-step mode) 동작하는 지 여부
● SF(Sign Flag) : 산술 결과가 양수면 0, 음수면 1로 세팅
● ZF(Zero Flag) : 연산 결과가 0이면 1로 세팅
● AF(Auxiliary Carry Flag)
● PF(Parity Flag)
● CF(Carry Flag) : 부호 없는 수의 오버플로가 발생했을 때, 1로 세팅
5# 바이트 오더링(Byte Ordering)
- 데이터를 저장하는 방식
변수타입 / byte 수 |
BYTE / 1 |
WORD / 2 |
DWORD / 4 |
char [6] / 6 |
값 |
0x01 |
0x0123 |
0x01234567 |
"abcde" |
빅 엔디언 |
[01] |
[01] [23] |
[01] [23] [45] [67] |
[61] [62] [63] [64] [65] [00] |
리틀 엔디언 |
[01] |
[23] [01] |
[67] [45] [23] [01] |
빅 엔디언(Big Endian) : 데이터를 순차적으로 저장, 주로 RISC계열의 CPU, 네트워크 프로토콜에서 사용
리틀 엔디언(Little Endian) : 데이터를 역순으로 저장, Intel계열의 CPU에서 주로 사용