Stack Frame
Sunrin/Layer7

Stack Frame

I. Stack Frame : RSP와 RBP로 스택을 관리하는 기법

1. RSP와 RBP

 ① RSP :  Stack Point Register

  - 스택이 움직일 때마다 움직이며 스택의 맨 꼭대기 부분을 가리킨다.

  - RBP의 반대 방향을 가리킨다.

 

 ② RBP : Base Point Register

  - RSP는 스택이 움직일 때마다 움직이지만

    RBP는 고정되어 있으며 움직이지 않는다.


2. 스택 (Stack)

 - 스택 영역은 함수의 호출과 관련되는 지역변수와 매개변수가 저장되는 영역이다.

 - 스택 영역은 함수 호출과 함께 할당된다. 함수의 호출이 끝나면 없어진다.

 - 후입선출(LIFO : Last In First Out) 구조이다.

   (프링글스 통, 엘리베이터 탑승 등을 생각하면 이해하기 쉽다.)


3. 스택프레임 (Stack Frame)

 - RSP와 RBP로 스택을 관리하는 기법이다.

 - 스택프레임에 의해서 스택을 관리한다.

 - 함수가 호출이 되면 스택에

    (1) 함수의 변수

    (2) 호출이 끝난 후 돌아갈 주소

   를 저장하는데, 이 스택에 저장된 정보를 스택프레임이라고 한다.

 

 - 스택프레임을 그림으로 봐 보자! 뾰로롱.

- rsp를 rbp에 저장하여 두 개의 위치를 같게 한다. ( 초기값을 같게 설정한다. )

 

 

 

 

 - 그림을 통해 알 수 있듯, RBP는 절대로 움직이지 않고 RSP는 스택이 변할 때마다 변한다.

 - RSP는 꼭대기를 가리키면 RBP와 반대 방향이다.


4. 함수 프롤로그와 에필로그

 4-(1) 함수 프롤로그

  push    rbp

     : 함수의 초기값을 스택에 저장한다.

  mov     rbp,rsp

     : 현재의 RSP를 RBP에 저장한다.


 4-(2) 함수 에필로그

  leave

     : RSP를 초기값으로 복원한다. 그리고 저장해뒀던 RBP값으로 복원한다.

  ret  

     : 함수를 종료한다.

 


II. PLT & GOT 

① PLT ( Procedure Linkage Table ) :

 - 실제로 호출할 코드를 담고 있는 테이블

 - 프로그램 밖에 있는 프로시저를 연결해주는 테이블

 - PLT를 이용해서 다른 라이브러리에 있는 프로시저를 호출하여 사용 가능하다.

 

프로시저 ( procedure ) ???

 - 프로그램을 여러 개의 단위로 분해한 것

 - 프로그램 수정과 관리가 쉬워지며, 다른 프로그램에서 재사용도 할 수 있다.

 

② GOT ( Global Offset Table ) :

 - PLT가 참조하는 테이블

 - 프로시저의 주소가 들어있다.

 

 

위에서 언급한 것 처럼 PLT가 GOT를 참조한다음 함수를 호출하는데,

이 때, 프로그램 밖에 있는 라이브러리에서 주소를 가져오게 된다.

 

함수 호출하기 전에 puts 함수가 0x400520 주소를 가진다.
함수 호출 종료 후에 주소값이 0x7ffff7a64a30으로 변했다.

 

 


III. 어셈블리 코드 흐름

 

main에 breakpoint를 걸어준다.

 

push rbp  rbp가 스택에 들어온다.
mov rbp, rsp rbp를 rsp에 복사한다. ( rbp와 rsp가 가리키는 주소가 같아진다.)
sub rsp, 0x100  rsp가 0x100 바이트 할당된 공간을 가리킨다.
mov eax, 0 eax가 0으로 초기화 된다.
call setup 함수를 호출한다.

 

 

leave

ret

 

위에 두 줄은 함수 에필로그이다. 함수를 종료한다.

 

 


IV. 디버거 사용법

 

1. 디버그와 디버거

 ① 디버그(Debug) : 프로그래밍 중 발생하는 버그를 찾고 수정하는 것. 코드에서 버그를 제거하는 것.

 ② 디버거(Debugger) : 디버그를 하는 도구. 디버거를 사용하여 디버그 할 수 있다.

 


2. 디버거 명령어

(1) 시작하고 종료하는 명령어

 - gdb 프로그램 이름 : 시작하기

 

 - q(quit) 또는 단축키 Ctrl+d : 종료하기

binary를 시작하고 끝냈다.

 

(2) 실행중인 바이너리를 제어하는 명령어

 - run(r) : 바이너리를 실행한다.

 

- breakpoint (b) : 실행 중인 프로그램을 멈추게 한다. (멈추는 지점)

0x00000000004006a8에 breakpoint를 지정했다.

 

 - continue (c) : 다음 브레이크 포인트까지 실행한다. 

 

 

 - next(ni) : 다음 행을 수행한다. 단, 함수를 만났을 때 함수 안으로 들어가지 않는다.

   -> next n : n번 수행한다. 

 - step(si) : 다음 행을 수행한다. 단, 함수를 만났을 때 함수 안으로 들어간다.

0x4006a8 <main>을 가리키고 있다.
nexti 명령어를 입력했다.
화살표가 0x4006a9 <main+1>을 가리키고 있다.

ni 명령어를 쳤더니 <main>을 가리키던 화살표가 다음 행인 <main+1>을 가리킨다.

 

 

 - kill : 디버깅 중인 프로그램을 실행 취소한다.

 - finish : 현재 함수를 수행하고 빠져나간다.

 - return : 현재 함수를 수행하지 않고 빠져나간다.

 

(3) 출력 관련 명령어

 - info(i) : 중단점의 정보 보기

   -> info breakpoint : 현재 설정된 브레이크 포인트의 정보를 출력한다.

   -> info function : 함수의 정보를 출력한다.

설정한 breakpoint를 출력한다.

 - print(p) : 출력하기

   -> print value : 

   -> print $register : 해당 레지스터 값 출력

 

(4) 메모리 보기 포맷과 출력형식

 - x 명령어는 메모리 특정 범위의 값들을 확인할 때 쓴다.

   -> x/[원하는 범위][출력 형식][단위]

   -> x/64x main

(5) 기타 명령어

 - disassemble 함수이름 : 함수를 디스어셈블(분해?)한다.

 - delete(d) 브레이크포인트 : 브레이크포인트를 삭제한다.

breakpoint를 설정하고 info 명령어를 통해 breakpoints를 확인할 수 있었지만 delete후에는 breakpoint가 삭제되어 확인할 수 없다.

 

 

 

 

 

 

 

 

 

'Sunrin > Layer7' 카테고리의 다른 글

Webhacking Project - PHP와 MySQL  (0) 2020.08.12
Dreamhack - Introduction of Webhacking 정리  (0) 2020.08.07
Python 문법  (0) 2020.07.08
C Pointer 실습  (0) 2020.07.03
C pointer  (0) 2020.06.24