본문 바로가기

카테고리 없음

리버싱에서의 레지스터란? ( +OllyDbg, 어셈블리어 기초 )

※ 프로그램 실행 과정 

HDD -> RAM -> CPU 순으로 옮겨가며 처리된다.



※ 레지스터 

: CPU 내부에 존재하는 고속 저장 장치. 프로그래밍의 관점에서 볼 때, 하나의 값을 저장할 수 있는 변수들 중 특별한 용도로 쓰이는 것으로 볼 수 있다. (레지스터는 CPU와 한 몸이기 때문에 고속으로 데이터를 처리할 수 있음)






※ OllyDbg

: 리버싱에서 많이 사용되는 프리웨어 중 하나인 OllyDbg라는 프로그램은 디스어셈블리와 디버깅이 가능한 툴이다. OllyDbg로 실행파일(.exe)파일을 열었을 때, 다음과 같은 정보를 보여준다.




 우측에 빨간색 네모로 표시된 곳에서 보여주는 내용은 레지스터, 플래그에 관한 정보이다.

프로그램을 실행시켰을 때 CPU내부의 레지스터 안에 저장되는 정보들을 보여준다.

아주 기초적인 디버깅을 위해 알아야하는 레지스터에 대한 지식들을 정리해보자.




※ IA-32 Register (Intel Architecture 32bits)


 IA-32에 존재하는 레지스터들은 아주 많지만, 우리는 디버깅의 초급 단계에서 알고 있어야 할 

Basic program execution registers에 대해서 알아보자.


Basic program execution registers는 다음과 같이 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-Pulpose Resgisters (범용 레지스터)

: 범용 레지스터는 이름처럼 범용적으로 막 사용되는 레지스터들이다. 보통은 상수/주소 등을 저장할 때 주로 사용되며, 특정 어셈블리 명령어에서는 특정 레지스터를 조작하기도 하고, 어떤 레지스터들은 특수한 용도로 사용되기도 한다.


레지스터 

용도 

EAX

 함수의 리턴값이 저장됨.

EBX

 간접 주소가 저장됨.

ECX

 반복 병령어 사용시 반복 카운터로 사용됨.

 (ECX>0인 동안 반복) 

EDX

 EAX의 보조

 (넘치는 걸 담아줌, 부호 확장 명령에 쓰임) 

EBP

 스택 프레임의 기준, 

 하나의 스택 프레임의 시작지점 주소가 저장됨.

ESP

 스택 프레임의 최상단, 

 하나의 스택 프레임의 끝지점 주소가 저장됨.

ESI

 (데이터 복사나 조작시) 출발지 주소(Source Index)가 저장됨.

EDI

 (데이터 복사나 조작시) 도착지 주소(Destination Index)가 저장됨.

 (주로 ESI레지스터가 가리키는 주소의 데이터가 복사된다.)

EIP

 Instruction Pointer



 EAX, EBX, ECX, EDX 이 4개의 레지스터들은 주로 산술연산(ADD, SUB, XOR, OR 등) 명령어에서 상수/변수 값의 저장 용도로 많이 사용된다.

어떤 어셈블리 명령어 (MUL, DIV, LODS 등)들은 특정 레지스터를 직접 조작하기도 한다. (이런 명령어가 실행된 이후에 특정 레지스터들의 값이 변경됨)


 EBP, ESP, ESI, EDI 이 4개의 레지스터들은 주로 메모리 주소를 저장하는 포인터로 사용된다.


□가 1byte 공간을 나타내는 것이고 ■로 해당되는 곳을 표시한 것이다. 

(예시는 EAX이지만 다른 범용 레지스터들도 적용됨)


EAX     4byte   ■■■■     ( EAX는 4Byte 공간을 가리킴 )

  └AX  2byte   □□■■     ( AX는 EAX의 하위 2Byte를 가리킴 )

      └AH 상위 1byte □□■□   ( AH는 AX의 상위 1Byte를 가리킴 )

      └AL 하위  1byte □□□■   ( AL은 AX의 하위 1Btyte를 가리킴 )



2. Segment Registers (세그먼트 레지스터)

: 세그먼트(Segment)란 IA-32의 메모리 관리 모델에서 나오는 용어이다.

세그먼트 레지스터 관련 내용은 리버싱 초보자에게 어려운 지식으므로 과감하게 스킵한 뒤 향후에 따로 공부하기로 하자. (어려워서 의욕이 상실 될 수 있으므로..)



3. Program Status and Control Register 

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


- EFLAGS (Flag Register) : 두가지 상태를 가짐. (0 : clear, 1 : set)

: 플래그 레지스터의 이름은 EFLAGS이며 32비트(8바이트) 크기이다.

32개 각각의 비트마다 의미를 가지고 있다.

각 비트는 1 또는 0 두가지 값을 가지는데, 이는 On/Off 혹은 True/False를 의미한다.

일부 비트는 시스템에서 직접 세팅하고, 일부 비트는 프로그램에서 사용된 명령의 수행 결과에 따라 세팅된다.


32개 각각의 비트들을 모두 이해하는 것은 너무 어려우므로,

리버싱 입문 단계에서는 애플리케이션 디버깅에 필요한 3가지 flag(ZF,OF,CF)에 대해서만 잘 이해하면 된다.




EFLAG 

상태 변화

 AF

 

 CF  (Carry Flag) 

 부호없는 수의 오버플로가 발생했을 때 1로 set됨.

 OF  (Overflow Flag)

 부호있는 수의 오버플로가 발생했을 때 1로 set됨.

 그리고  MSB(Most Significant Bit)가 변경되었을 때 1로  set됨.

 PF

 

 SF  (Sign Flag)

 연산 결과가 음수가 되었을 때 1로 set됨.

 ZF  (Zero Flag)

 산술 연산 결과가 0일때 1로 set됨.



4. Instruction Pointer


 다음 실행될 명령어가 존재하는 메모리의 주소가 저장되는 레지스터이며 크기는 32비트(4바이트)이다.

CPU는 EIP에 저장된 메모리 주소의 명령어를 하나 처리하고 난 후 자동으로 그 명령어 길이만큼 EIP를 증가시킨다. 이런 식으로 계속 명령어를 처리해 나간다.

범용 레지스터들과는 다르게 EIP는 그 값을 직접 변경할 수 없도록 되어있어서 다른 명령어(JMP, CALL, RET, jcc), 인터럽트, 예외발생을 통하여 간접적으로 변경해야 한다.







※ 데이터 형식


주요 데이터 타입 

사용 용도 

BYTE 

부호 없는 1byte

WORD

부호 없는 2byte 

DWORD 

부호 없는 4byte





※ 표시 형식


주요 피연산자 표시 기호 

mem 

메모리 (변수)

label

지정된 레이블 

imm

상수, 즉시 값 (16진수)

reg

범용 레지스터


 명령어  피연산자 (operand,  ','로 구분)

 

즉, ADD mem , imm 의 경우,

ADD a 0x0A 
     a   : 메모리 ( 내가 할당해준 변수 a [EBP-0x04]를 나타냄 )
  0x0A : 상수 ( 16진수로 10을 나타냄 )

위와 같이 피연산자를 입력해야 한다는 뜻이다.




도움이 되었다면 소중한 공감/댓글 부탁드려요 !!

감사합니다.