프로세스 구조
프로세스 구조 deep dive
- Python 프로그램
- func(1, 2)가 실행되면 Return Address가 STACK에 저장되고 그 다음 func(1, 2)의 argument인 a, b가 저장
- func(1, 2)가 종료되면 STACK에 남아있는 주소를 확인하여 그 주소의 코드를 실행
- C 프로그램
- main()이 실행되어 main 이후의 코드 주소인 0006h가 STACK에 저장됨
- main()의 argument argc, argv가 차례대로 STACK에 저장됨
- main() 내부에서 meaningless(1)가 실행되어 meaningless(1) 이후의 코드 주소인 0005h가 STACK에 저장됨
- meaningless()의 argument data가 STACK에 저장됨
- meaningless()의 지역 변수 temp가 STACK에 저장됨
- meaningless()가 종료되면 STACK에 남아있는 주소를 PC에 저장하고 0005h의 코드를 실행
- main()이 종료되면 STACK에 남아있는 주소를 PC에 저장하고 0006h의 코드를 실행
프로세스와 컨텍스트 스위칭
- 프로세스의 구성
- text(CODE): 코드
- data: 전역 변수, 정적 변수
- stack: 임시 데이터(함수 호출, 로컬 변수 등)
- heap: 코드에서 동적으로 만들어지는 데이터 (ex. C언어 malloc())
- PC(Program Counter): 프로그램의 코드 주소를 가리키는 레지스터
- SP(Stack Pointer): Stack Frame의 최상단 주소를 가리키는 레지스터
- 000h-0002h 영역의 코드에서는 레지스터의 변화가 없다.
- 0003h에서 func()가 실행될 때 EBP에 저장된 주소값 1000h가 STACK에 저장된다.
- func()의 return address가 이어 저장된다.
- 지역 변수 a, b의 값이 저장된다.
- SP는 STACK의 최상단 주소인 0FFCh를 저장한다.
- EBP는 SP의 값을 저장하고 EBP에 저장된 주소값 0FFCh가 STACK에 저장된다.
- func()의 반환값 3은 EAX에 저장되고 func()가 종료되었으므로 STACK의 b = 2, a = 1이 삭제된다.
- PC가 0004h로 바뀌고 이후의 코드를 실행한다.
Heap이란?
프로세스 실행 도중 동적으로 데이터를 저장할 경우 heap 영역에 저장된다. C언어에서는 malloc(), Python이나 Java에서는 객체를 heap 영역에 저장한다.
프로세스 구조와 스택 오버플로우
초기값이 할당된 전역 변수는 DATA 영역에, 선언만 된 전역변수는 BSS에 저장된다.
- 스택 오버플로우: 주로 해커들의 공격에 활용되었음
void copy (char *bar)
{
char data[6];
strcpy(data, bar);
}
int main (int argc, char **argv)
{
copy(argv[1]);
}
위의 예제에서 argv[1] = ‘aaaaaacc’ 일 경우 data에 지정된 공간을 넘어 엉뚱한 공간에 침입할 수 있다.