본문으로 바로가기

본 게시물은 필자가 개념을 외우기위해서 포스팅했습니다. 이내용은 매우 주관적입니다. 


참고문서 -> 해커 지망자들이 알아야 할 Buffer Overflow Attack의 기초 by 달고나 (Dalgona@wowhacker.org)


8086 메모리의 구조  - 커널과 가용메모리로 이루어져있다.

커널이 아랫부분이고( 낮은주소 ) 가용메모리가 윗부분 (높은주소) 

시스템은 운영에 필요한 기본적인 명령어 집합을 커널에서 찾는다.


하나의 프로세스 는 하나의 프로그램이 실행되기 위한 메모리 구조이다.

운영체제는 하나의 프로세스를 실행시키면 이 프로세스를 segment라는 단위로 묶어서 가용 메모리 영역에 저장시킨다.

가용메모리 영역에는 여러개의 segment가 저장될 수 있다.

하나의 segment는 code segment, data segment, stack segment로 이루어진다.


Low Address

   [  코드   ] 

   [ 데이터 ]

   [    힙    ] 

   [  스택   ] 

High Address


code segment에는 시스템이 알아들을 수 있는 명령어 즉 instruction들이 들어 있다.

instruction들은 명령을 수행하면서 많은 분기 과정과 점프, 시스템 호출 등을 수행하게 되는데 분기와 점프의 경우 메모리 상의 특정 위치에 있는 명령을 지정해 주어야 한다. 하지만 segment는 자신이 현재 메모리 상에 어느 위치에 저장될지 컴파일 과정에서는 알 수 없기 떄문에 정확한 주소를 지정할 수 없다. 그래서 segmetn에서는 logical address를 사용한다. Logical address는 실제 메모리 상의 주소 (Physical address)와 매핑되어 있다. 즉 segment는 segment selector에 의해서 자신의 시작 위치(offset)를 찾을 수 있고 자신의 시작 위치로부터의 위치(logical address)에 있는 명령을 수행할 지를 결정하게 되는 것이다. 따라서 실제 메모리 주소느 physical address는 offest + logical address 라고 할 수 있다.


data segment에는 프로그램이 실행시에 사용되는 데이터(전역변수)가 들어간다. 


stack segment는 현재 수행되고 있는 handler, task, program이 저장하는 데이터 영역으로 우리가 사용하는 버퍼가 바로 이 stack segment에 자리잡게 된다.


※ 레지스터와 플레그에 대한 설명은 생략


push  %ebp

mov   %esp,%ebp


ebp를 저장하는 이유는 이전에 수행하던 함수의 데이터를 보존하기 위해서이다. 이것을 base pointer라고도 부른다. 그래서 함수가 시작될 때에는 이렇게 stack pointer와 base pointer를 새로 지정하는데 이러한 과정을 함수 프롤로그 과정이라고 한다.


call 명령은 함수를 호출할 떄 사용되는 명령으로 함수 실행이 끝난 다음 다시 이후 명령을 계속 수행할 수 있도록 이후 명령이 있는 주소를 스택에 넣은 다음 EIP에 함수의 시작 지점의 주소를 넣는다.


leave instruction은 함수 프롤로그 작업을 되돌리는 역할을 한다. 위에서 본 대로 함수 프롤로그는


push  %ebp

mov   %esp,%ebp

였다. 이것을 되돌리는 작업은

mov  %ebp,%esp

pop  %ebp

이다.

laave instruction 하나가 위의 두 가지 일을 한꺼번에 하는 것이다. stack pointer를 이전의 base pointer로 잡아서 function()함수에서 확장했던 스택 공간을 없애버리고 Push해서 저장해 두었던 이전 함수 즉, main()함수의 base pointer를 복원시킨다.


ret instruction은 이전 함수로 return하라는 의미이다. eip레지스터에 return address를 pop하여 집어넣는 역할을 한다.


버퍼(buffer)란 시스템이 연산 작업을 하는데 있어 필요한 데이터를 일시적으로 메모리 상의 어데인가 저장하는데 그 저장 공간을 말한다.