https://dreamhack.io/
해커들의 놀이터, Dreamhack
해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향
dreamhack.io
System Hacking 부분 Stage 2를 기반으로 정리 및 공부한 내용입니다.
어셈블리 명령어를 위한 기초 배경
- 컴퓨터 구조
- 명령어 집합 구조
- 인텔 x86-64 아키텍처
- 인텔 x86-64 아키텍처의 레지스터들
- 컴퓨터 구조(Computer Architecture)
- 명령어 집합 구조(Instruction Set Architecture, ISA)
- 범용 레지스터(General Register)
- 세그먼트 레지스터(Segment Register)
- 플래그 레지스터(Flag Register)
- 명령어 포인터 레지스터(Instruction Pointer Register, IP)
컴퓨터의 부품
1) CPU는 컴퓨터의 작동에 핵심이 되는 연산을 처리
2) 저장장치는 데이터를 저장
3) GPU는 그래픽 데이터를 처리
4) 랜카드는 네트워크 통신을 처리
5) 사운드 카드는 소리 데이터를 처리
컴퓨터라는 기계로 작동할 수 있는 것은 컴퓨터에 대한 기본 설계가 존재하고, 이 설계에 맞춰서 여러 하드웨어가 개발되고 이들을 조립해서 컴퓨터가 완성된다. 이러한 설계가 바로 컴퓨터 구조이다.
1. 컴퓨터 구조
컴퓨터구조(Computer Architecture)
: 컴퓨터가 효율적으로 작동할 수 있도록 하드웨어 및 소프트웨어의 기능을 고안하고, 이들을 구성하는 방법
: 아래 4가지 등이 포함됨.
- 컴퓨터의 기능 구조에 대한 설계
- 명령어 집합구조
- 마이크로 아키텍처
- 기타 하드웨어 및 컴퓨팅 방법에 대한 설계
컴퓨터 기능 구조에 대한 설계
: 컴퓨터가 연산을 효울적으로 하기 위해 어떤 기능이 컴퓨터에 필요한지 고민하고 설계하는 분야.
대표 예) 폰 노이만 구조, 하버드 구조, 수정된 하버드 구조
명령어 집합구조(ISA)
: 전체적인 컴퓨터 구조 중에서 특히 CPU가 사용하는 명령어와 관련된 설계
: 가장 널리 사용되는 ISA 중 하나가 인텔의 x86-64 아키텍처이다.
대표 예) ARM, MIPS, AVR, 인텔의 x86 및 s86-64등이 있음.
다양한 이유 : 컴퓨팅 환경 다양, 각 컴퓨터의 다른 수준의 연산 능력
마이크로 아키텍처(MA)
: CPU가 처리해야 하는 명령어를 설계하는 분야.
: 정의된 명령어 집합을 효울적으로 처리할 수 있도록 CPU의 회로를 설계하는 분야
ex) 캐시 설계, 파이프라이닝, 슈퍼 스칼라, 분기 예측, 비순차적 명령어 처리
하드웨어 및 컴퓨팅 방법론
: 직접 메모리 접근
** 현대적 컴퓨터의 기능 구조에 큰 영향을 끼쳤다고 평가받는 폰 노이만 구조와 명령어 집합 구조(그 중 x86-64 아키텍처)에 대해 더 자세히 알아보는 코스이다**
# 폰 노이만 구조
: 연산 및 제어(중앙처리장치 - CPU), 저장(기억장치 - Memory)의 세 가지 핵심 기능과 기능을 쓰는 구조.
: 추가적으로 장치간에 데이터나 제어 신호를 교환할 수 있도록 버스(bus)라는 전자 통로도 사용한다.
1) 중앙처리장치(CPU)
: 프로그램의 연산을 처리하고 시스템을 관리하는 컴퓨터의 두뇌.
: 프로세스의 코드를 불러오고 실행하고 결과를 저장하는 일련의 모든 과정이 여기서 일어난다.
: 아래 세 가지의 장치로 구성된다.
- 산술논리장치(산술/논리 연산 처리) Aka. ALU
- 제어장치(CPU를 제어)
- 레지스터(CPU에 필요한 데이터를 저장)
2) 기억장치
: 컴퓨터가 동작하는데 필요한 여러 데이터를 저장하기 위해 사용됨.
: 용도에 따라 주기억장치와 보조기억장치로 분류됨.
<주기억 장치>
프로그램 실행과정에서 필요한 데이터들을 임시로 저장하기 위해 사용됨
(대표적으로 RAM) // Random-Access Memory
<보조기억 장치>
운영체제, 프로그램 등과 같은 데이터를 장기간 보관하고자 할 때 사용됨
(대표적으로 하드 드라이브[HDD], SSD(Soild State Drive)가 있음.
3) 버스
: 컴퓨터 부품과 부품 사이 또는 컴퓨터와 컴퓨터 사이에 신호를 전송하는 통로
대표적 예시
<데이터 버스> 데이터 이동
<주소 버스> 주소 지정
<제어버스> 읽기/쓰기 제어
+) 랜선, 데이터 전송 소프트웨어, 프로토콜 등
4) etc : 기억장치가 있는데 굳이 CPU에 register가 있는 이유??
CPU도 필요한 데이터를 빠르게 공급하고, 반출할 수 있어야 자신의 효율을 제대로 발휘할 수 있다.
하지만, CPU의 연산속도가 기억장치와의 데이터 교환속도보다 압도적으로 빠르기 때문에, 기억장치만을 사용하면 병목현상이 발생한다.
따라서 CPU는 교환속도를 획기적으로 단축하기 위해 레지스터와 캐시라는 저장장치를 내부에 갖고 있다고 한다.
# 명령어 집합 구조
: CPU가 해석하는 명령어의 집합.
: 프로그램은 기계어로 이루어져 있고 실행하면 이 명령어들을 CPU가 읽고 처리한다.
: 인텔의 x86-64는 고성능 프로세서를 설계하기 위해 사용되는데 주로 데스크톱 또는 랩톱에 쓰인다. 현재 인텔의 x86기반 CPU의 점유율이 압도적이기 때문에 x86-64가 가장 많이 사용된다.
# x86-64
n 비트 아키텍쳐
: CPU가 한 번에 처리할 수 있는 데이터의 크기이며 설계상 n비트의 데이터까지만 처리할 수 있게 된다.
: CPU가 이해할 수 있는 데이터의 단위라는 의미에서 WORD라고 부흔다.
word가 크면 좋은 점.
: 더 많은 가상메모리를 사용할 수 있다. 현재 많이 사용 중인 64비트 아키텍처에서는 이론상 16,777,216TB까지 가상 메모리가 제공될 수 있다고 한다.
여담(x86-84의 여러 이름)
: Intel64, IA-32e, EM64T 또는 amd64라고 불린다. 개발 역사에 따라서 다름.
x86-64의 아키텍처: 레지스터
- 레지스터는 CPU가 데이터를 빠르게 저장하고 사용할 때 이용하는 보관소이며 산술 연산에 필요한 데이터를 저장하거나 주소를 저장하고 참조하는 등 다양한 용도로 사용되고 있다.
- x64 아키텍처에는 여러 개의 레지스터가 존재한다.
1) 범용 레지스터(General Register)
2) 세그먼트 레지스터(Segment Register)
3) 명령어 포인터 레지스터(Instruction Pointer Register, IP)
4) 플래그 레지스터(Flag Register)
1) 범용 레지스터
: 범용이라는 말 그대로 주 용도는 있지만 그 외의 다양한 용도로 사용될 수 있는 레지스터이다.
8바이트를 저장할 수 있으며, 부호 없는 정수를 기준으로 2^64 - 1까지의 수를 나타낼 수 있다.
자주 쓰이는 범용 레지스터들의 주용도는 아래와 같다. 이 외에도 x64에는 r8, r9, ..... , r15까 있다고 한다.
이름 | 주용도 |
rax (accumulator register) | 함수의 반환 값 |
rbx (base register) | x64에서는 주된 용도 없음 |
rcx (counter register) | 반복문의 반복 횟수, 각종 연산의 시행 횟수 |
rdx (data register) | x64에서는 주된 용도 없음 |
rsi (source index) | 데이터를 옮길 때 원본을 가리키는 포인터 |
rdi (destination index) | 데이터를 옮길 때 목적지를 가리키는 포인터 |
rsp (stack pointer) | 사용중인 스택의 위치를 가리키는 포인터 |
rbp (stack base pointer) | 스택의 바닥을 가리키는 포인터 |
2) 세그먼트 리지스터
: x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터가 존재하며 각각의 크기는 15비트이다. 이는 x64로 아키텍처가 확장되면서 용도에 큰 변화가 생긴 레지스터이다.
: 현대의 x64에서 cs, ds, ss 레지스터는 코드 영역과 데이터, 스택 메모리 영역을 가리킬 때 사용되고, 나머지 레지스터는 운영체제 별로 용도를 결정할 수 있도록 범용적인 용도로 제작된 세그먼트 레지스터이다.
3) 명령어 포인터 레지스터
: CPU가 어느 부분의 코드를 실행할지 가리키는 것이 이의 역할이다.
: x64 아키텍처의 명령어 레지스터는 rip이고 크기는 8바이트이다.
4) 플래그 레지스터 : 프로세서의 현재 상태를 저장하고 있는 레지스터
깃발을 올리고 내리는 행위로 신호를 전달하듯이 자신을 구성하는 여러 비트들로 CPU의 현재 상태를 표현한다.
x64 아키텍처에는 RFLAGS라 불리는 64비트의 플래그 레지스터가 존재한다.
RFLAGS는 64비트여서 최대 64개의 플래그를 쓸 수 있지만 실제로는 20개만 쓴다고 한다.
주로 쓸 것은 아래와 같다.
플래그 | 의미 |
CF(Carry Flag) | 부호 없는 수의 연산 결과가 비트의 범위를 넘을 경우 설정 됩니다. |
ZF(Zero Flag) | 연산의 결과가 0일 경우 설정 됩니다. |
SF(Sign Flag) | 연산의 결과가 음수일 경우 설정 됩니다. |
OF(Overflow Flag) | 부호 있는 수의 연산 결과가 비트 범위를 넘을 경우 설정 됩니다. |
5) 레지스터 호환
x86-64 아키텍처는 IA-32의 64비트 확장 아키텍처이며, 호환이 가능하다. IA-32에서 CPU의 레지스터들은 32비트 크기를 가지며, 이들의 명칭은 각각 eax, ebx, ecx, edx, esi, edi, esp, ebp였다. 호환성을 위해 이 레지스터들은 x86-64에서도 그대로 사용이 가능하다.
앞서 소개된 rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp가 이들의 확장된 형태이며, eax, ebx 등은 확장된 레지스터의 하위 32비트를 가르킨다. 예를 들어, eax는 rax의 하위 32비트를 의미한다.
또한 마찬가지로 과거 16비트 아키텍처인 IA-16과의 호환을 위해 ax, bx, cx, dx, si, di, sp, bp는 eax, ebx, ecx, edx, esi, edi, esp ,ebp의 하위 16비트를 가르킨다.
이들 중 몇몇은 다시 상위 8비트, 하위 8비트로 나뉘는데 이에 관한 것은 오른쪽 사진에서 볼 수 있다.

# 퀴즈를 풀면서...
이론에서 하위 16비트나 8비트나 이런 것이 뭔지 잘 이해가 안되었는데 문제를 풀고 이론을 다시 보니까 의미를 정확히 이해 할 수 있었다.
0x는 64비트를 사용한 것을 의미한 것이고 한 글자 당 4비트 즉 4*16=64로 생각하면 된다. 하위 32비트이면 뒤의 8자리이고 이것이 eax가 된다. 그렇다면 eax는 32비트가 되고 eax의 하위 16비트이면 뒤의 4자리가 되는 것이며 ax가 되고 상위 8비트(2자리)가 ah가, 하위 8비트(2자리)가 al이 된다.
+) 꼭 잊지 않기 위해 공부하고 나서 바로 바로 기록하자.
'Hacking & Security > System Hacking' 카테고리의 다른 글
System Hacking(3) - 3 : x64 Assembly : Essential part(2) (0) | 2022.01.29 |
---|---|
System Hacking(3) - 3 : x64 Assembly : Essential part(1) (1) | 2022.01.29 |
System Hacking (3) -2 : Linux Memory Layout (0) | 2022.01.28 |
System Hacking(2) (0) | 2022.01.21 |
System Hacking(1) [installing Ubuntu & Bandit level 0 ->5] (0) | 2022.01.18 |