Reversing

[리버싱-기초]IA-32 레지스터

SteffenLee 2022. 11. 30. 04:36

CPU 레지스터란?

CPU 내부에 존재하는 다목적 저장공간입니다. 우리가 일반적으로 알고 있는 RAM과는 다릅니다.

CPU가 RAM에 접근하려면 물리적으로 접근해야해서 시간이 오래걸립니다.

하지만 레지스터는 CPU 내부에 존재하기 때문에 빠르게 접근할 수 있습니다.

 

IA-32 레지스터

IA-32레지스터는 인텔 아키텍쳐 32비트 기반 레지스터입니다. 

 

범용 레지스터

말 그래도 범용적으로 사용되는 레지스터입니다. IA-32 기준 각 각의 범용 레지스터들의 크기는 32비트(4바이트)입니다.

대체적으로 상수/주소 등을 저장할 때 사용되며 특정 어셈블리 명령어에서는 특정 레지스터를 조작하기도 합니다.

 

아래 4개의 레지스터는 주로 산술연산(and, sub, xor, or 등) 명령어에서 상수/변수 값의 저장 용도로 사용됩니다.

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

 

ECX는 반복문에서 반복 카운트로 사용됩니다.(루프를 돌때마다 ECX 값이 1씩 감소)

EAX는 함수 리턴 값에 사용됩니다. 따라서 모든 Win32 API 함수들은 리턴 값을 EAX에 저장시킨 후 리턴합니다.

 

추가로 주의해야할 사항이 있다면 Win32 API 함수들은 내부에서 ECX와 EDX를 사용합니다. 따라서 API가 호출이되면 ECX와 EDX 값이 변경되므로 ECX에 DEX 중요한 값이 저장되어 있다면 다른 레지스터나 스택에 백업을 해야합니다.

 

아래 4개의 레지스터들은 주로 메모리 주소를 저장하는 포인터로 사용됩니다.

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)

 

ESP는 스택 메모리 주소를 가리키고, PUSH/POP/CALL/RET 명령어는 ESP를 직접 조작합니다.

특히 스택 메모리 관리는 프로그램 측면에서 매우 중요하므로 ESP는 다른 용도로 사용하면 안됩니다.

EBP는 함수가 호출될 때의 ESP를 저장하고 있다가 함수가 리턴하기 직전에 ESP에 값을 돌려줘야합니다. 이것을 Stack Frame 기법이라고 합니다.

ESI와 EDI는 LODS, STOS, REP MOVS 같은 특정 명령어와 함께 메모리 복사에 사용됩니다.

 

세그먼트 레지스터

세그먼트는 IA-32의 메모리 관리 모델에서 나오는 용어입니다.

세그먼트란 메모리를 조각내어 각 조각마다 시작 주소, 범위, 접근 권한 등을 부여해서 메모리를 보호하는 기법입니다.

또한 페이징 기법과 함께 가상 메모리를 실제 물리 메모리로 변경할 때 사용됩니다.

 

각 세그먼트 레지스터의 이름은 아래와 같습니다.

CS: Code Segement

SS: Stack Segement

DS: Data Segement

ES: Extra(Data) Segement

FS: Data Segement

GS: Data Segement

 

프로그램 상태와 컨트롤 레지스터

플레그 레지스터 이름은 EFLAGS(: Flag Register)이며 32비트(4바이트)크기 입니다.

각 비트마다 의미를 가지고 있고, 0과 1의 값을 가집니다.(on/off || true/false)

이 레지스터의 32개의 비트의 의미를 이해하는 것은 힘드므로 3가지 flag(ZF, OF, CF)에 대해서만 이해하면 됩니다.

 

ZF: Zero Flag --> 연산 명령 후에 결과 값이 0이면 플래그가 1로 설정됩니다.

OF: Overflow Flag --> 부호 있는 수의 오버플로우가 발생했을 때 1로 세팅됩니다. 그리고 MSB가 변경되었을 때 1로 세팅됩니다.

CF: Carry Flag --> 부호 없는 수의 오버플로우가 발생했을 때 1로 세팅됩니다.

 

그리고 마지막으로

EIP레지스터가 있는데 이 레지스터는 CPU가 처리할 명령어의 주소를 나타네는 레지스터이며 크기는 32비트입니다.

CPU는 EIP에 저장된 메모리 주소의 명령어 하나를 처리한 후 자동으로 그 명령어 길이만큼 EIP를 증가시킵니다.

 

범용 레지스터들과는 다르게 EIP는 그 값을 직접 변경할 수 없어서 변경하고 싶다면 특정 명령어(JMP, Jcc, CALL, RET)를 사용하거나

인터럽트, 예외를 발생시켜야 합니다.

 

감사합니다.