본문 바로가기

리버싱/리버싱핵심원리

3, 4장 요약(바이트 오더링, IA-32 Register)

바이트 오더링

데이터를 저장하는 방식을 말하는 것으로 빅 엔디언과 리틀 엔디언 방식이 있다

 

빅 엔디언 & 리틀 엔디언

1) 빅 엔디언

  • 사람이 보는 방식과 동일하게 앞에서부터 순차적으로 저장
  • 대형 UNIX 서버에 사용되는 RISC 계열의 CPU, 네트워크 프로토콜에서 많이 사용
  • 애플리케이션 개발에 사용된 데이터를 네트워크로 송수신할 때 엔디언 타입을 변경해야 한다

2) 리틀 엔디언

  • 데이터를 역순으로 저장
  • Intel x86 CPU에서 리틀 엔디언 방식을 사용
  • 산술 연산과 데이터의 타입이 확장/축소될 때 효율적

 

CPU 레지스터

레지스터란 CPU 내부에 존재하는 다목적 저장 공간

 

Basic program execution registers

  • General Purpose Registers (32비트 - 8개)
  • Segment Registers (16비트 - 6개)
  • Program Status and Control Register (32비트 - 1개)
  • Instruction Pointer (32비트 - 1개)

1) 범용 레지스터

IA-32에서 각각의 범용 레지스터들의 크기는 32비트(4바이트)이다.

보통 상수/주소 등을 저장할 때 주로 사용, 특정 어셈블리 명령어에서는 특정 레지스터를 조작하기도 한다.

 

EAX, EBX, ECX, EDX 레지스터는 주로 산술연산 명령어에서 상수/변수 값의 저장 용도로 많이 사용된다

 

- EAX(Extended Accumulator Register)

산술(덧셈, 곱셈, 나눗셈 등), 논리연산을 수행하며 일반적으로 함수 리턴값을 저장한다. 모든 Win32 API 함수들은 리턴값을 EAX에 저장 후 리턴

 

- EBX(Extended Base Register)

ESI 레지스터나 EDI 레지스터와 결합될 수 있으며, 이 EBX 레지스터는 메모리 주소를 저장하기 위한 용도로 사용

 

- ECX(Extended Count Register)

반복 명령어(LOOP)에서 반복 카운트(loop count)로 사용(루프를 돌 때마다 ECX를 1씩 감소시킴)

 

- EDX(Extended Data Register)

EAX와 함께 복잡한 연산을 위한 추가적인 데이터(부호 확장 등)를 저장할 때 사용

 

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

 

 

EBP, ESP, ESI, EDI 레지스터는 메모리 주소를 저장하는 포인터로 사용된다

 

- EBP(Extemded Base Pointer)

함수가 호출되었을 때 그 순간의 ESP를 저장하고 있다가, 함수가 리턴하기 직전에 다시 ESP에 값을 되돌려줘서 스택이 깨지지 않도록 한다(Stack Frame 기법)

 

- ESP(Extemded Stack Pointer)

스택 메모리 주소를 가리킨다. 어떤 명령어들(PUSH, POP, CALL, RET)은 ESP를 직접 조작하기도 한다

 

- ESI(Extended Source Index)

DS 레지스터가 가리키는 Data Segment 내의 어느 데이터를 가리키고 있는 포인터. 문자열 처리에서 Source를 가리킴

 

- EDI(Extended Destination Index)

ES 레지스터가 가리키고 있는 Data Segment 내의 어느 데이터를 가리키고 있는 포인터. 문자열 처리에서 Destination을 가리킴

 

2) 세그먼트 레지스터

IA-32 보호 모드에서 세그먼트란 메모리를 조각내어 각 조각마다 시작 주소, 범위, 접근 권한 등을 부여해서 메모리를 보호하는 기법으로 세그먼트는 페이징 기법과 함께 가상 메모리를 실제 물리 메모리로 변경할 때 사용된다

 

각 세그먼트 레지스터가 가리키는 세그먼트 디스크립터와 가상메모리가 조합되어 선형주소가 되며, 페이징 기법에 의해 선형주소가 최종적으로 물리주소로 변환된다

 

- CS : Code Segment

- SS : Stack Segment

- DS : Data Segment

- ES : Extra(Data) Segment

- FS : Data Segment

- GS : Data Segment

 

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

EFLAGS : Flag Register

 

EFLAGS 레지스터는 각 비트는 1 또는 0의 값을 가지는데, On/Off 또는 True/False를 의미한다

 

32비트가 있으나 일단 중요한 3개만 알아두자

- Zero Flag(ZF) : 연산 명령 후에 결과값이 0이 되면 ZF가 1(True)로 세팅

 

- Overflow Flag(OF) : 부호 잇는 수의 오버플로가 발생했을 때, MSB(Most Significant Bit)가 변경되었을 때 1로 세팅

 

- Carry Flag(CF) : 부호 없는 수의 오버플로가 발생했을 때 1로 세팅

 

4) Instruction Pointer(EIP)

- CPU가 처리할 명령어의 주소를 나타내는 레지스터

- 범용 레지스터들과는 다르게 EIP는 그 값을 직접 변경할 수 없도록 되어 있어 다른 명령어를 통해 간접적으로 변경

- EIP를 변경할 때는 특정 명령어(JMP, Jcc, CALL, RET)를 사용하거나 인터럽트, 예외를 발생시켜야 한다

'리버싱 > 리버싱핵심원리' 카테고리의 다른 글

PE File Format(EAT)  (0) 2019.12.01
PE File Format(IAT)  (0) 2019.11.29
PE File Format(Dos Header ~ Optional Header)  (0) 2019.08.26
Process Explorer, 함수 호출 규약  (0) 2019.08.25
1, 2장 요약  (0) 2019.08.24