1. 스택
- 스택(stack) : 쌓아놓은 더미
- LIFO(Last-In First-Out) : 가장 최근에 들어온 데이터가 가장 먼저 나감
- 실행 흐름의 제어와 함수 호출 관리에 도움을 줌
- 함수가 호출될 때마다 해당 함수의 실행 정보를 저장하는 스택프레임이 스택에 쌓이고, 함수의 실행이 완료되면 스택프레임이 제거됨
프로그램의 스택을 공격하여 잘못된 실행 흐름을 유도하거나, 버퍼 오버플로우 등을 활용하여 악의적인 코드를 주입 가능함
시스템 또는 프로그램의 보안 침해 가능
- push() : 스택에 데이터를 추가
- pop() : 스택에서 데이터를 삭제
- peek(s) : 요소를 스택에서 삭제하지 않고 보기만 하는 연산
- is_empty(s) : 스택이 공백상태인지 검사
- is_full(s) : 스택이 포화상태인지 검사
- create() : 스택 생성
#define MAX_STACK_SIZE 100
typedef int element;
typedef struct {
element data[MAX_STACK_SIZE];
int top;
}StackType;
// 스택 초기화 함수
void init_stack(StackType *s) {
s->top = -1;
}
// 공백 상태 검출 함수
int is_empty(StackType*s) {
return (s->top == -1);
}
// 포화 상태 검출 함수
int is_full(StackType*s) {
return (s->top == (MAX_STACK_SIZE -1));
}
// 삽입 함수
void push(StackType*s, element item) {
if (is_full(s)) {
fprintf(stderr, "스택포화에러\n");
return;
}
else s->data[++(s->top)] = item;
}
// 삭제 함수
element pop(StackType*s) {
if (is_empty(s)) {
fprintf(stderr, "스택공백에러\n");
exit(1);
}
else return s->data[(s->top)--];
}
int main(void) {
StackType s;
init_stack(&s);
push(&s, 1);
push(&s, 2);
push(&s, 3);
printf("%d\n",pop(&s)); // 3
printf("%d\n",pop(&s)); // 2
printf("%d\n",pop(&s)); // 1
}
2. 스택프레임(StackFrame)
- 함수가 호출될 때 생성되는 메모리 공간
- 함수 실행 정보의 유지에 도움을 줌
- 함수의 실행 정보와 지역 변수들이 저장됨
- 프로그램에서 함수가 호출되면 해당 함수의 스택프레임이 스택 메모리에 할당되고, 함수의 실행이 완료되면 스택프레임이 제거
- 후입선출(Last-In, First-Out)구조인 스택(Stack)에 저장 -> 함수 호출과 반환을 관리하는 데 유용함
주로 스택프레임을 이용하여 함수 호출 및 반환의 흐름을 조작
ex) 스택프레임을 조작하여 제어를 반환할 주소를 변경하면, 프로그램의 실행이 예상치 못한 곳으로 이동 가능
이를 이용한 공격은 주로 버퍼 오버플로우와 함께 사용되며, 시스템 보안을 우회하거나 제어할 수 있음
3. 레지스터(Register)
- 레지스터(Register)는 CPU 내부에 위치한 저장 공간
- 데이터의 효율적인 처리에 도움을 줌
- 프로세서가 데이터를 처리하고 조작할 때 레지스터를 사용하여 임시로 데이터를 저장하거나 연산에 필요한 값을 보관
- 각 CPU 아키텍처마다 다양한 종류와 수의 레지스터가 존재하며, 명령어를 실행하는 동안에만 존재하는 일시적인 저장소 역할을 함
레지스터는 CPU 내부에서 데이터를 처리하는 데 사용되기 때문에, 레지스터 값을 조작하는 것은 프로그램의 동작을 변경할 수 있는 강력한 도구
레지스터를 조작하여 프로그램의 상태를 변조하거나 악성 코드를 삽입하여 시스템 제어를 획득 할 수 있음
해킹에서의 활용
- 버퍼 오버플로우 공격 : 해커는 스택을 이용하여 버퍼 오버플로우를 유발하게 되고, 스택프레임을 조작하여 악성 코드를 실행시킴
- ROP(Return-Oriented Programming) 공격 : 해커는 레지스터 값을 조작하여 프로그램의 실행 흐름을 변경하고, 스택프레임을 활용하여 실행을 제어함
보안 조치
- 스택 가드(Stack Guard) : 스택에 특별한 값들을 추가해 버퍼 오버플로우를 감지하고 방어함
- NX-bit(No-Execute bit) : 스택과 메모리에 실행 권한을 제어해 악성 코드의 주입을 방지
- ASLR(Address Space Layout Randomization) : 메모리 주소의 무작위화를 통해 공격자가 예측하기 어렵게 함