내가 제일 어려워하는 부분이다. 진짜 어렵다. 많이 어렵다. 매번 리버스 엔지니어링을 공부하면 이 부분에서 포기하였다. 끝까지 해보자!@!~@!@
레지스터?
레지스터가 무엇일까? 레지스터는 CPU 내부에 있는 다목적 저장 공간이다. CPU가 RAM의 정보를 읽기 위해서는 물리적으로 시간이 좀 걸리지만, CPU 내부의 레지스터는 한 몸이라 고속으로 데이터를 처리할 수 있다.
IA-32 레지스터 안에는 기능도 무척 많고 그에 따른 종류도 많다. 그런 많은 종류들 중에서 Basic program execution register에 대하여 알아보자.
Basic program execution register
이 레지스터는 4개의 그룹으로 나눌 수 있다.
- General Purpose Registers (32비트 - 8개)
- Segment Registers (16비트 - 6개)
- Program Status and Control Register (32비트 - 1개)
- Instruction Pointer (32비트 - 1개)
1. 범용 레지스터 (General Purpose Registers)
IA-32의 범용 레지스터들의 크기는 32비트(4바이트)로, 보통은 상수/주소 등을 저장할 때 사용되며, 특정 어셈블리 명령에서는 특정 레지스터를 조작하기도 한다. 특수한 용도로 사용되기도 하는 범용 레지스터들도 있다.(그럼 왜 범용이야..)
각 레지스터들은 16비트 하위 호환을 위하여 구획이 나뉜다.
EAX의 경우 32비트이다.
EAX안에는 AX가 존재하는데 AX는 EAX의 하위 16비트이다. 또한 AH는 AX의 상위 8비트, AL은 AX의 하위 8비트이다.
이러한 점을 이용하여 잘 쓰면 효율적으로 사용할 수 있을 것이다.
각각의 레지스터에 대하여 알아보자.
EAX : Accumulator for operands and results data -> 함수 리턴 값
EBX : Pointer to data in the DS segment
ECX : Counter for string and loop operations -> LOOP에서 반복 카운트(loop count)로 사용, 돌 때마다 ECX 1 감소
EDX : I/O pointer
위 4개의 레지스터들은 산술 연산(ADD, SUB, XOR, OR...) 등에서 상수나 변수의 저장 용도로 주로 사용된다.
어떤 어셈블리어 명령어(MUL, DIV, LODS...)들은 특정 레지스터를 직접 조작하기도 한다.
EAX, ECX는 기본적으로는 산술 연산에 사용되지만, 필요한 경우 특수한 목적으로 사용 가능하다.
Win32 API 함수들은 내부에서 ECX와 EDX를 사용한다. 그래서 API 호출되면 ECX와 EDX 같은 값은 변경되므로 중요한 값이라면 호출되기 전에 백업해주자.
나머지 4개의 범용 레지스터를 알아보자.
EBP : Pointer to data on the stack (in the SS segment) -> ESP와 상호작용 하며 스택 깨짐 방지(Stack Frame)
ESI : source pointer for string operations
EDI : destination pointer for string operations
ESP : Stack pointer (in the SS segment) -> 스택 메모리 주소
이 레지스터들은 주로 메모리 주소를 저장하는 포인터로 사용된다. PUSH, POP, CALL, RET 같은 명령어들은 ESP를 직접 조작시킨다.
EBP는 함수가 호출되었을 때 그 순간의 ESP를 저장하고 있다가, 함수 리턴 전에 ESP에 값을 되돌려줘 스택이 깨지지 않도록 함
ESI, EDI는 특정 명령어들(LODS, STOS, REP MOVS등)과 함께 메모리 복사에 사용
2. 세그먼트 레지스터 (Segment Registers)
[세그먼트 레지스터는 어렵다. 그리니 심각하게 읽지는 말구 리버싱 실력이 늘었을 때 다시 복습하자.]
세그먼트(Segment)란 IA-32의 메모리 관리 모델에서 나오는 용어다.
더 구체적으로 들어가자면 메모리를 조각내어 각 조각마다 시작 주소, 범위, 접근 권한 등을 부여해 메모리를 보호하는 기법이다.
세그먼트는 페이징 기법과 함께 가상 메모리를 실제 메로리로 변경할 때 사용되기도 한다.
세그먼트 메모리는 SDT(Segment Descriptor Table) 이라는 곳에 기술되어 있는데, 세그먼트 레지스터는 바로 이 SDT의 index를 가지고 있다.
위 그림은 보호 모드에서의 세그먼트 메모리 모델을 나타내고 있다.
세그먼트 레지스터에는 CS, SS, DS, ES, FS, GS 총 6개 있다. (각각의 크기는 16비트(2바이트)이다.)
각각 Segment Register가 가리키는 Segment Descriptors와 가상 메모리가 조합되어 선형주소(Linear Address)가 되고,
페이징 기법에 의해 선형 주소가 최종적으로 물리주소로 변환된다.
이게 무슨 소리일까.............. 아직 잘 모르겠다 그냥 겉보기로 보이는 선형주소는 사실 선형주소가 아니라 리버싱 하기 어렵게 뒤죽박죽으로 만들었다. 이정도로 생각해야겠다. 그래도 각각 세그먼트 레지스터들의 이름을 알아보도록 하자.
CS : Code Segment
SS : Stack Segment
DS : Data Segment
ES : Extra(Data) Segment
FS : Data Segment
GS : Data Segment
FS, GS의 약어가 궁금해 구글링 해봤는데, ES 다음의 문자가 F, G기 때문에 정해졌다고 한다. (아무의미 없다.)
FS Register의 경우 애플리케이션 디버깅에도 자주 등장하는데, SEH(Structured Exception Handling), PEB(Process Environment Block), TEB(Thread Environment Block)의 주소를 계산할 때 사용된다.
무슨소리야...
3. 프로그램 상태와 컨트롤 레지스터
EFLAGS : Flag Register플래그(Flag) 레지스터의 이름은 EFLAGS이고, 32비트이다. (16비트인 FLAGS의 확장형태)
위 그림과 같이 각 비트는 1 또는 0의 값을 가지고 있는데, 이는 True/False(On/Off)를 의미한다.
일부 비트는 시스템에서 세팅하고, 일부 비트는 프로그램에서 명령의 수행 결과에 따라 세팅된다.
EFLAGS 레지스터 32개를 모두 이해하는 것은 어렵다. 그러니 ZF, OF, CF만 우선 잘 이해하자.
(조건분기명령인 Jcc에서 위 세 Flag 값을 확인하고 동작 수행 여부를 결정하기 때문)
Zero Flag(ZF)
- 연산 명령 후에 결과 값이 0이 되면 ZF가 1(True)가 된다.
Overflow Flag(OF)
- 부호 있는 수(Signed Integer)에서 오버플로우가 발생하면 1이 된다. 또한, MSB(Most Significant Bit)가 변경되었을 때 1로 세팅된다.
Carry Flag(CF)
- 부호 없는 수(Unsigned Integer)의 오버플로우가 발생하면 1이 됨
OF, CF는 많이 헷갈릴것이다. 디버깅을 여러번 해가면서 연습하자.
4. Instruction Pointer
EIP : Instruction Pointer
Instruction Pointer는 CPU가 처리할 명령어의 주소를 나타내는 레지스터이고, 크기는 32비트이다. (16비트인 IP 확장형태)
CPU는 EIP에 저장된 메모리 주소의 명령어(Instruction)을 처리하고 자동으로 그 명령어 길이만큼 EIP를 증가시킨다.
???????????? 명령어 길이만큼 EIP를 증가시킨다는게 무슨소리인지 모르겠다. 구글링을 해봐도 이러한 점에 관한 내용은 딱히 없다. 우선 넘어가자
EIP는 범용레지스터가 아니라 직접적으로 변경할 수 없다. JMP, Jcc, CALL, RET을 사용하거나, Interrupt, Exception을 발생시켜 바꿔야 한다.
EIP를 괴롭히면 해킹에 성공할지도 ...?
이번 내용은 개념이 너무 어렵당 직접 디버깅을 해보면서 익히고 싶당.
'공부 > 리버싱핵심원리' 카테고리의 다른 글
6장 abex' crackme #1 - 책의 풀이 (0) | 2020.12.01 |
---|---|
6장 abex' crackme #1 - 나의 풀이 (0) | 2020.11.30 |
5장 스택 (0) | 2020.11.30 |
3장 리틀 엔디언 표기법 (1) | 2020.11.28 |
2장 Hello, World! 리버싱 (0) | 2020.11.28 |