System Hacking | 로드맵 | Dreamhack
System Hacking
시스템 해킹을 공부하기 위한 로드맵입니다.
dreamhack.io
세그먼트(Segment)
적재되는 데이터의 용도별로 메모리의 구획을 나눈 것.
- 코드 세그먼트: 실행 가능한 기계 코드가 위치하는 영역 (=텍스트 세그먼트(Text Segment))
프로그램을 실행하려면 읽기 권한과 실행 권한은 있어야하므로 권한을 가지고 있지만, 쓰기 권한은 공격자가 악의적인 코드를 삽입하기 쉬우므로 현대 운영체제에는 코드 세그먼트에 쓰기 권한을 제거한다.
- 데이터 세그먼트: 컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치하는 영역
CPU가 해당 세그먼트의 내용을 읽을 수 있어야 하므로 읽기 권한을 가지고 있다. 데이터 세그먼트는 쓰기가 가능한 세그먼트와 쓰기가 불가능한 세그먼트로 다시 나눌 수 있다.
? 전역 변수와 같이 프로그램이 실행되면서 값이 변할 수 있는 데이터들은 쓰기가 가능한 세그먼트로 분류.(=data 세그먼트)
? 전역으로 선언된 상수와 같이 값이 변하면 안되는 데이터들은 쓰기가 불가능한 세그먼트로 분류.(=rodata 세그먼트)
- BSS 세그먼트(Block Started By Symbol Segment): 컴파일 시점에 값이 정해지지 않은 전역 변수가 위치하는 영역
대표적으로 개발자들이 선언만 하고 초기화하지 않은 전역 변수 등이 이 곳에 포함된다. 이 세그먼트에는 읽기 권한과 쓰기 권한이 부여되며, 메모리 영역은 프로그램이 시작될 때, 모두 0으로 값이 초기화된다.
? 이런 특성 때문에 C 코드를 작성할 때, 초기화되지 않은 전역 변수의 값은 0이 되는 것이다!
- 스택 세그먼트: 프로세스의 스택이 위치하는 영역
함수의 인자나 지역 변수와 같은 임시 변수들이 이곳에 포함된다. 읽기 권한과 쓰기 권한을 가진다.
스택 세그먼트는 스택 프레임(Stack Frame) 이라는 단위로 사용되는데, 프로그램이 실행 될때 얼마만큼의 스택 프레임을 사용할지는 예측이 어렵다. 그래서 운영체제는 프로세스를 시작할 때 작은 크기의 스택 세그먼트를 먼저 할당해주고, 부족해 질 때마다 이를 확장해주는 방식을 사용한다.
? 스택에 대해서 ‘아래로 자란다' 라는 표현을 종종 사용하는데, 이는 스택이 확장될 때, 기존 주소보다 낮은 주소로 확장되기 때문이다.
- 힙 세그먼트: 힙 데이터가 위치하는 영역
스택과 마찬가지로 실행중에 동적으로 할당될 수 있으며, 리눅스에서는 스택 세그먼트와 반대 방향으로 자란다. 읽기 권한과 쓰기 권한을 가진다.
? 스택 세그먼트와 같은 방향으로 자라면, 힙 세그먼트를 확장하는 과정에서 스택 세그먼트와 충돌할 수 있다. 이를 방지하기 위해 리눅스는 스택을 메모리의 맨 끝에 배치시키고 반대로 자라게 한다.
정리
세그먼트
|
역할
|
일반적인 권한
|
사용 예
|
코드 세그먼트
|
실행 가능한 코드가 저장된 영역
|
읽기, 실행
|
main() 등의 함수 코드
|
데이터 세그먼트
|
초기화된 전역 변수 또는 상수가 위치하는 영역
|
읽기와 쓰기 또는 읽기 전용
|
초기화된 전역 변수, 전역 상수
|
BSS 세그먼트
|
초기화되지 않은 데이터가 위치하는 영역
|
읽기, 쓰기
|
초기화되지 않은 전역 변수
|
스택 세그먼트
|
임시 변수가 저장되는 영역
|
읽기, 쓰기
|
지역 변수, 함수의 인자 등
|
힙 세그먼트
|
실행중에 동적으로 사용되는 영역
|
읽기, 쓰기
|
malloc(), calloc() 등으로 할당 받은 메모
|
어셈블리 언어(Assembly Language)
컴퓨터에서 주로 사용하는 기계어가 난해하고 복잡하자, David Wheeler는 EDSAC을 개발하면서 어셈블리 언어(Assembly Language)와 어셈블러(Assembler)라는 것을 고안하게 되었다.
- 개발자들이 어셈블리어로 코드를 작성 → 컴퓨터가 이해할 수 있는 기계어로 코드를 치환
기계어를 어셈블리 언어로 번역하는 역어셈블러(Disassembler)도 개발되어 소프트웨어를 분석하는데 이용하고 있다.
x64 어셈블리 언어
기본 구조🧱
명령어(Operation Code, Opcode)
+
피연산자(Operand)
명령어 (Operation Code, Opcode) 🔫
명령
|
코드
|
데이터 이동(Data Transfer)
|
mov, lea
|
산술 연산(Arithmetic)
|
inc, dec, add, sub
|
논리 연산(Logical)
|
and, or, xor, not
|
비교(Comparison)
|
cmp, test
|
분기(Branch)
|
jmp, je, jg
|
스택(Stack)
|
push, pop
|
프로시져(Procedure)
|
call, ret, leave
|
시스템 콜(System call)
|
syscall
|
피연산자 (Operand) 🎯
- 상수(Immediate Value)
- 레지스터(Register)
- 메모리(Memory)
메모리 피연산자는 []으로 둘러싸인 것으로 표현되며, 앞에 크기 지정자(Size Directive) TYPE PTR이 추가될 수 있다. 여기서 타입에는 BYTE, WORD, DWORD, QWORD가 올 수 있으며, 각각 1바이트, 2바이트, 4바이트, 8바이트의 크기를 지정한다.
예시
메모리
|
피연산자
|
QWORD PTR [0x8048000]
|
0x8048000의 데이터를 8바이트만큼 참조
|
DWORD PTR [0x8048000]
|
0x8048000의 데이터를 4바이트만큼 참조
|
WORD PTR [rax]
|
rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조
|
'Study > Ping!' 카테고리의 다른 글
System hacking: 시스템 해킹 키워드 정리 (0) | 2025.04.06 |
---|---|
1학기 1주차 : 드림핵 시스템 해킹 Background-Computer Science 01 (0) | 2025.03.04 |
6주차 과제: 드림핵 비기너즈, 네트워크 (0) | 2025.03.02 |
5주차 과제: 드림핵 비기너즈 02 (0) | 2025.02.23 |
5주차 과제: 드림핵 비기너즈 01 (0) | 2025.02.23 |