리버싱 핵심 원리
[1주]
3장 - 리틀 엔디언 표기법
바이트 오더링(Byte Ordering)은 데이터를 저장하는 방식.
크게 2가지 방식이 있다 :
1. 빅 엔디언(Big Endian)
2. 리틀 엔디런(Little Endian)
어떻게 다른지 보자
1바이트의 자료형을 저장할떄는 차이가 없다. 자료형의 크기가 2바이트 이상이면 차이가 난다.
빅 엔디언 |
리틀 엔디언 |
데이터를 저장할 때 앞에서부터 순차적으로 저장 한다. | 저장되는 바이트의 순서가 뒤집혀 있다. |
RISC 계열의 CPU에서 사용됨. 네트워크 프롵콜에서 사용됨. |
Intel x86 CPU에서 사용됨. |
장점 : 사람이 보기에 직관적이다 |
장점 : 산술 연산과 데이터의 타입이 확장/축소될 때 더 효율적이다. |
※ str 문자열은 엔디언 형식과 상관없이 동일하다. 문자열은 캐릭터(char) 배열이기 때문에 각 바이트를 하나씩 연속해서 저장하기 때문.
※ 네트워크 프로토콜에서 빅 엔디언이 사용되고 x86 계열의 응용 프로그램은 리틀 엔디언을 사용하기 때문에 애플리케이션의 개발에 사용된 데이터를 네트워크로 송수신할 때 엔디언 타입을 변경해야 한다.
실제로 OllyDbg에서 Dump창을 보면 값들이 리틀 엔디언 형식으로 저장된걸 확인할 수 있다.
4장 - IA-32 Register 기본 설명
(IA-32 = Intel Architecture 32비트)
IA-32는 많은 레지스터가 있는데, 디버깅 할 때 제일 많이 보게 되는 레지스터는 Basic program execution register다.
Basic program execution register는 4개로 나눌 수 있다:
1. 범용 레지스터 (General purpose registers) (32비트 - 8개)
2. Segment Registers (16비트 -6개)
3. Program Status and Control Register (32비트 - 1개)
4. Instruction Pointer (32비트 - 1개)
1. 범용 레지스터 (General Purpose Registers)
막(?) 쓰이는 레지스터다
EAX : Accumulator for operands and results data
EBX : Pointer to data in the DS segment
ECX : Counter for string and loop operations
EDX : I/O pointer
EAX, EBX, ECX, EDX 는 산술연산(ADD, SUB, XOR, OR 등) 명령어에서 상수/변수 값의 저장 용도로 많이 쓰임.
ECX - 반복문 명령어(LOOP)에서 loop count로 사용됨.(루프를 돌때마다 ECX를 1씩 감소함)
EAX - 함수 리턴 값에 사용됨. (모든 Win32 API 함수는 리턴 값을 EAX에 저장한 후 리턴한다.)
EBP : Pointer to data on the stack (in the SS segment)
ESI : source pointer for string operations
EDI : destination pointer for string operations
ESP : Stack pointer (in the SS segment)
EBP, ESI, EDI, ESP는 주로 메모리 주소를 저장하는 포인터로 사용됨.
ESP - 스택 메모리 주소를 가리킴
EBP - 함수가 호출 되었을때 그 순간의 ESP를 저장하고 있다가, 함수가 리턴하기 직전에 ESP에 값을 되돌려줘서 스택이 깨지지 않도록 한다.(Stack Frame 기법)
2. 세그먼트 레지스터 (Segment Registers)
세그먼트란?
* IA-32 보호모드에서 세그먼트란 메모리를 조각내어 각조각마다 시작주소, 범위,접근권한 등을 부여해서 메 모리를 보호하는 기법이다.
* 세그먼트는 Paging 기법과 함께 가상 메모리를 실제 물리 메모리로 변경할 때 사용된다.
* 세그먼트 메모리는 Segment Descriptor Table(SDT)이라고 하는 곳에 기술되어 있는데,세그먼트 레지스터 는 바로 이 SDT의 index를 가지고 있다.
세그먼트 레지스터는 6개 CS, SS, DS, ES, FS, GS. 각각 16비트.
각 세그먼트 레지스터가 가리키는 세그멘트 디스크립터(Segment Descriptor)와 가상 메모리가 조합되어 선형주소(Linear Address)가 된다. ( 세그먼트 디스크립터 + 가상 메모리 = 선형주소). 그리고 페이징 기법에 의해서 선형주소가 최종적으로 물리주소(Physical Address)로 변환된다. ( 선형주소 --(페이징기법)--> 물리주소 )
CS : Code Segment
SS : Stack Segment
DS : Data Segment
ES : Extra(Data) Segment
FS : Data Segment
GS : Data Segment
※ FS 레지스터는 SEH(Structure Exception Handling), TEB(Thread Environment Block), PEB(Process Environment Block) 등의 주소를 계산할 때 사용됨.
3. 프로그램 상태와 컨트롤 레지스터 (Program Status and Control Register)
EFLAGS : Flag Register
각 비트마다 의미를 가지고 있다.
ZF(Zero Flag) : 연산 명령 후에 결고 값이 0이 되면 ZF가 1(True)로 세팅된다.
OF(Overflow Flag) : Signed integer의 오버플로우가 발새했을 때 1로 세팅됨. MSB(Most Significant Bit)가 변경되었을 때 1로 세팅됨.
CF(Carry Flag) : Unsigned integer의 오버플로우가 발생했을 때 1로 세팅됨.
4. Instruction Pointer
EIP - Instruction Pointer
CPU가 처리할 명령어의 주소를 나타내는 레지스터. CPU는 EIP에 저장된 메모리의 주소의 명령어 하나를 처리하고 난 후 자동으로 그 명령어 길이만큼 EIP를 증가 시킨다.
※ EIP는 그 값을 직접적으로 변경할 수 없도록 되어있다. 다른 명령어를 통해 간접적으로 변경해야한다. 변경하고 싶을 때는 특정 명령어 (JMP, Jcc, CALL, RET)를 사용하거나 interrupt, exception을 발생시켜야 한다.
'[보안 Archive] ~2017 > 리버싱 핵심 원리' 카테고리의 다른 글
[2주] 7장- 스택 프레임 (0) | 2015.03.16 |
---|---|
[1주] 5장~6장 - 스택 & abex crackme #1 (0) | 2015.03.09 |
[1주] 1장~2장 (0) | 2015.03.09 |
댓글