x86_64

Dreamer_01·2022년 4월 30일
0

리버싱 (Reversing)

목록 보기
3/4
post-thumbnail

이 포스팅은 드림핵 리버싱 강의를 따릅니다.

x86 아키텍처

x86 아키텍처는 우리가 익히 아는 Intel사의 64비트 체제 아키텍처 이다.
이전에는 32비트 체제가 존재하였으나, 부족한 점이 있어 확장시킨것이 64비트 체제이다.

확장을 하게된 이유는 메모리 공간이 부족해서 인데, 이를 살펴보려면 32비트, 64비트 같이 ~~ 비트 운영체제 라고 하는 것의 의미를 먼저 알아야 한다.

n 비트 운영체제란?

32비트, 64비트 운영체제에서 각각 32,64가 뜻하는 바는 연산의 단위를 뜻하며 이를 컴퓨터과학에서는 WORD라고 칭한다.

예를 들면, 32비트 운영체제에서의 속의 ALU(Arithmetic and Logical Unit :산술 연산 장치)는 모두 32비트를 기준으로 연산을 진행하며, 그안의 있는 부속품들인, 레지스터의 크기, 버스들의 대역폭등이 모두 32비트로 세팅되어 있다는 뜻이다.

레지스터

레지스터란, cpu의 연산을 위해 임시적으로 데이터를 저장하는 장치이다.
주로 임시적인 데이터를 저장하는 곳을 RAM, 반영구적인 데이터를 저장하는 곳을 하드 디스크라고 하여, 레지스터와 RAM을 서로 헷갈릴 수도 있다.
하지만 RAM보다 더 CPU에 가깝게 위치하여, 더 빠른 연산을 위해 도와주는 것을 레지스터라고 이해하면 되겠다.

하드 디스크,RAM,레지스터중 레지스터가 제일 용량이 적지만, 연산 속도는 가장 빠르다. 또한 CPU는 자체적으로 데이터를 저장할 수 없으므로, 이를 대체하기 위해 레지스터가 위치한다.

레지스터의 기능으로는 저장 능력도 있지만, 데이터를 읽어오는 것도 중요하다.
레지스터의 용량은 큰편이 아니므로, 계속해서 데이터를 새로 읽어오는 기능이 필요하다.
이를 위해 특정 메모리 주소를 가리키는 기능을 탑재하고 그 주소를 기반으로 데이터를 읽어오는 기능을 지원한다.

레지스터의 종류

  1. 범용 레지스터
    이름에서 알 수 있듯, 주용도는 있으나 범용적으로도 사용할 수 있는 레지스터를 뜻한다.
    x86_64에서는 앞에 r을 붙여서 기존의 32비트 아키텍처에서 사용되는 범용레지스터와 구별한다.
    각각의 범용레지스터는 8바이트를 저장할 수있으며, 2^64 -1 만큼의 부호없는 정수를 표현할 수 있다.

  2. 세그먼트 레지스터
    세그먼트 레지스터에는 cs(code segment), ss(stack segment), ds(data segment), es, fs, gs 가 존재하며 es,fs,gs는 모두 여분의 data segment이다.
    과거의 16비트 체제에서는 offset:segment라는 주소 체제를 표현하기 위해서 사용되었다. 이를 통해서 16비트 밖에 표현하지 못했던 것이 20비트까지 표현될 수 있도록 한다.
    하지만 이제 64비트 체제가 되면서, 메모리가 부족해지지 않아지면서 스택 메모리 영역, 코드 영역, 데이터 영역을 가리키는데 사용된다.
    각각의 세그먼트 레지스터 크기는 16비트이다. 이것은 16비트든 64비트든 16비트(2바이트)의 크기를 가지고 있으며 이는 호환성을 위해 그렇게 구성되었다.

  3. 명령어 포인터 레지스터
    프로그램의 코드는 기계어로 구성되어 있기 때문에, 이중에서 프로그램이 어느 곳을 가리키고 있는지 표기하는 레지스터로 rip라는 레지스터로 명명되어 있으며, 크기는 8바이트이다.

  4. 플래그 레지스터
    플래그 레지스터는 프로세서의 현재 상태를 표시하는 레지스터이다. 과거의 16비트에서 확장된 RFLAGS라는 레지스터로 존재하며, 자신을 구성하는 비트들로 프로세서의 상태를 나타낸다.

    주로 사용되는 플래그 레지스터의 값(플래그)로는 밑의 그림을 참고한다.

버스

버스란, 컴퓨터 부품들 간에 데이터를 이동시키는 길이라고 이야기 할 수 있겠다.
초기에는 실제 물리적으로 구현하였으나, 현재는 논리적으로 구현하고 있다.
버스의 예로는, 입출력 장치와 연결된 입출력 버스, 메모리의 값이 돌아다니는 메모리 버스 등이 있다.

WORD의 크기가 가지는 의미

32비트가 64비트로 확장된 이유는 제공하는 가상메모리의 크기 차이이다.
32비트 체제에서 지원하는 가상메모리의 크기는 2의 32제곱 바이트인 4,294,967,296바이트 즉 4기가 바이트이지만, 이론상 64비트 체제는 2의 64제곱 바이트 즉, 16,777,216 테라바이트까지 메모리가 지원된다.

이같은 용량의 차이는 기존의 32비트에서 작동되기엔 한계를 가지고 있던 게임, 전문 소프트웨어 같은 프로그램들이 64비트에서는 무리없이 작동될 수 있도록 해주었고, 그래서 현재의 많은 컴퓨터들의 64비트 체제를 가지고 있는 cpu를 사용한다.

가상메모리(Virtual Memory)
가상메모리는 기존의 주기억장치(RAM 등)가 지원하는 공간이 부족해서 보조기억장치의 공간을 주기억장치의 공간처럼 가상으로 가져오는 기술을 이른다.
이로써 각 프로그램에 전달되는 주소는 실제 메모리 주소인 물리주소가 아니고, 가상의 주소인 논리적인 주소가 전달된다. 이 주소들은 후에 MMU라는 메모리 관리 장치로 인해 실제 메모리로 치환된다.
(이 기술 덕에 프로그래머는 메모리 주소를 인지하며 프로그램을 짤 필요가 없어졌다.)

강좌 속 문제 해설


1번 문제를 보면, rax의 값이 0x0123456789abcdef인데, 레지스터의 그림을 보면 eax는 rax의 반절이다. 그러므로 (1)번의 답은 rax값의 반인 0x89abcdef이다.
(2)번은 ax레지스터의 값을 묻는 것으로, eax레지스터의 반절인 0xcdef이다.
(3)(4)번도 같은 흐름으로 이해할 수 있을 것이다.

위의 문제와 같이 레지스터의 크기가 발달되면서 이전의 레지스터와 호환하기 위해서 구조를 계속 이어나간것을 볼 수 있다.

0개의 댓글