우리집에 GDB 있는데... 메모리 보고갈래? #02

By in09 | March 10, 2016

우리집에 GDB 있는데… 메모리 보고갈래? #02





Day#2 애프터 신청 (너 gdb 사용법, 갖고싶다.. 너란 stack )



tomato.c

//tomato.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
 
void func2() {
    puts("func2()");
}
 
void sum(int a, int b) {
    printf("sum : %d\n", a+b);
    func2();
}
 
int main(int argc, char *argv[]) {
 
    int num=0;
    char arr[10];
 
    sum(1,2);
    strcpy(arr,argv[1]);
    printf("arr: %s\n", arr);
    if(num==1){
        system("/bin/sh");
    }
    return 0;
}


compile

$ gcc -fno-stack-protector -o tomato tomato.c


-fno-stack-protector 옵션을 포함하는 이유

gcc가 스택을 보호하기 위해 canary라는 것을 삽입해요.
함수 내에서 사용하는 스택 프레임과 return address 사이에 canary를 넣어염.
Buffer Overflow가 발생해 canary를 덮었을 때, 이를 감지하고 프로그램을 강제 종료 해 버린답니당!
이를 SSP(Stack Smashing Protection) 이라고 해요.
여기에선 오버플로우가 발생해도 프로그램이 강제 종료되지 않도록 –fno-stack-protector 옵션을 사용해 보호기법을 해제한겁니답 반대로 모든 프로시져에 이 보호기법을 적용하기 위해서는 -fstack-protector-all 옵션을 사용하세염




1. GDB 사용법



” 하라니까 하겠는데, 근데 gdb를 왜 써야되는데?”

지..진정하세요;;

gdb는 오픈소스로 공개되어있는 무료 디버거랍니다.  
아 디버거가 뭐냐거여?  

님들 해답지보고 공부할 때  
왜 이러저러하게 이 답이 도출이 되는지 보잖아요  

디버거도 그런검미다  
코드에서 이 라인을 실행할 때 어떤 값이 어떤 메모리 주소에 올라가고  
그 과정을 보여주는거져  

컴퓨터 계의 X-RAY랄까?  

gdb를 쓰면 물론 콘솔 기반이라.. 처음 쓸 때는 좀 어렵고 빡치고 하긴 해여..  
ida 봐봐여… 아름답잖아요..  
하지만 ELF 파일과 같은 Linux 기반의 실행파일을  
동적으로 따라가며 분석할 때 gdb 참 쓸만하져  
그래서 이거 씀미다!  

긍까 쫄지말고 긔긔!!  




gdb로 tomato를 실행시켜봅시당!


$ gdb ./tomato

이건 그냥 gdb로 tomato에 붙은 것에 불과해여.
아직 우리의 토마토는 실행되지 않았담미다.

일단 gdb 켜봤으면 뭐.. 어셈도 한번 봐주고
tomato를 실행하기 전에 이것 저것 설정도 해줘야쥬?
일단 보기 편하게 어셈 코드를 intel 형식으로 설정해
main을 출력해 보겠습니답ㅎㅎ


◎ GDB 사용법 1

  • set disassembly-flavor [명령어 형식]
    • 어셈블리 코드 문법을 설정하는 명령어
    • x86에서 Intel과 at&t 둘 중 하나를 골라 쓰면 됨
    • [명령어 형식의 예] : intel, att


◎ GDB 사용법 2

  • disas [함수이름]
    • 함수의 어셈블리 코드를 보는 명령어
(gdb) disas main
Dump of assembler code for function main:
   0x080484cf <+0>:	    push   ebp
   0x080484d0 <+1>:	    mov    ebp,esp
   0x080484d2 <+3>:	    sub    esp,0x10
   0x080484d5 <+6>:	    mov    DWORD PTR [ebp-0x4],0x0
   0x080484dc <+13>:	push   0x2
   0x080484de <+15>:	push   0x1
   0x080484e0 <+17>:	call   0x80484ae <sum>
   0x080484e5 <+22>:	add    esp,0x8
   0x080484e8 <+25>:	mov    eax,DWORD PTR [ebp+0xc]
   0x080484eb <+28>:	add    eax,0x4
   0x080484ee <+31>:	mov    eax,DWORD PTR [eax]
   0x080484f0 <+33>:	push   eax
   0x080484f1 <+34>:	lea    eax,[ebp-0xe]
   0x080484f4 <+37>:	push   eax
   0x080484f5 <+38>:	call   0x8048350 <strcpy@plt>
   0x080484fa <+43>:	add    esp,0x8
   0x080484fd <+46>:	lea    eax,[ebp-0xe]
   0x08048500 <+49>:	push   eax
   0x08048501 <+50>:	push   0x80485c2
   0x08048506 <+55>:	call   0x8048340 <printf@plt>
   0x0804850b <+60>:	add    esp,0x8
   0x0804850e <+63>:	cmp    DWORD PTR [ebp-0x4],0x1
   0x08048512 <+67>:	jne    0x8048521 <main+82>
   0x08048514 <+69>:	push   0x80485cb
   0x08048519 <+74>:	call   0x8048370 <system@plt>
   0x0804851e <+79>:	add    esp,0x4
   0x08048521 <+82>:	mov    eax,0x0
   0x08048526 <+87>:	leave
   0x08048527 <+88>:	ret
End of assembler dump.


메인이 이렇게 구성되어 있네요.
mainbreakpoint를 걸고 한번 실행해 볼까요?


        0x080484cf <+0>:	    push   ebp


요 부분이 main의 시작이잖아요?


◎ GDB 사용법 3

  • b *[메모리주소]
    • breakpoint를 거는 명령
    • [메모리 주소][함수의 이름] 혹은 이를 기준으로 한 [offset <+0>]으로 breakpoint를 걸어도 됩니당
    • breakpoint를 걸 땐, 주소 앞에 *를 붙이세요!
(gdb) b * main
Breakpoint 1 at 0x80484cf
(gdb) b *0x80484cf
Note: breakpoint 1 also set at pc 0x80484cf.
Breakpoint 2 at 0x80484cf
(gdb) b *main+0
Note: breakpoints 1 and 2 also set at pc 0x80484cf.
Breakpoint 3 at 0x80484cf


모두 똑같은 곳에 breakpoint가 걸렸죠?

breakpoint 정보를 확인해볼게용


◎ GDB 사용법 4

  • info b
    • breakpoint 정보를 열람할 수 있는 명령어
(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080484cf <main>
2       breakpoint     keep y   0x080484cf <main>
3       breakpoint     keep y   0x080484cf <main>


Breakpoint가 중복되니 삭제해보도록 하겠습니당!


◎ GDB 사용법 5

  • d [breakpoint 번호]
    • breakpoint를 삭제 할 수 있는 명령어
(gdb) d 3
(gdb) d 2
(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080484cf <main>


이제 프로그램을 실행해볼게요!
이제야 비로소.. 아 토마토 다 뿔었겠네ㅡㅡ


◎ GDB 사용법 6

  • run [매개변수]
    • gdb 내부에서 프로그램 실행
(gdb) run aaaaaaaaaa
Starting program: tomato aaaaaaaaaa

Breakpoint 1, 0x080484cf in main ()
(gdb)


헌데 명령행 인자로 main의 매개변수에 값이 넘어가죠? 그래서 aaaaaaaaa 스트링을 넘겨준 거예요.


$ ./tomato aaaaaaaaaa
sum : 3
func2()
arr: aaaaaaaaaa


터미널에서 위와 같이 실행하는 것과 동일한거죠!

현재 우리 실행 흐름이 어디에 있는지 EIP를 확인해볼게요!
Main에 멈춰있어야겠죠?


(gdb) r aaaaaaaaaa
Starting program: tomato aaaaaaaaaa

Breakpoint 1, 0x080484cf in main ()
(gdb) disas main
Dump of assembler code for function main:
=> 0x080484cf <+0>:	push   ebp
   0x080484d0 <+1>:	mov    ebp,esp
   0x080484d2 <+3>:	sub    esp,0x10


=> 화살표가 보이졍?
아주 잘 멈춰져있네요.
인스트럭션을 한줄 한줄 실행해볼게염


◎ GDB 사용법 7

  • ni
    • 다음 인스트럭션 실행
(gdb) ni
0x080484d0 in main ()
(gdb) ni
0x080484d2 in main ()
(gdb) disas main
Dump of assembler code for function main:
   0x080484cf <+0>:	push   ebp
   0x080484d0 <+1>:	mov    ebp,esp
=> 0x080484d2 <+3>:	sub    esp,0x10
   0x080484d5 <+6>:	mov    DWORD PTR [ebp-0x4],0x0
   0x080484dc <+13>:	push   0x2
   0x080484de <+15>:	push   0x1


현재 EIP가 멈춰져있는 곳 이 전의 밑줄 친 인스트럭션을 보면
esp 값을 ebp 값에 저장하고 있죠?
esp, ebp는 스택과 관련한 레지스터잖아요!
그 메모리에 어떤 값이 담겨있는지 gdb로 확인해보도록 하게씀미당!

그 전에 메모리 출력 방식에 대해 정리하고 가도록 할게요.
몇 바이트만큼 그리고 몇 진법으로 출력할 것인지 정해 옵션을 주어 출력해 주면 됨미다.


◎ GDB 사용법 8

  • x/b
    • 1바이트 출력
  • x/h
    • 2바이트 출력
  • x/w
    • 4바이트 출력
(gdb) x/b 0x080484cf
0x80484cf <main>:	0x55
(gdb) x/h 0x080484cf
0x80484cf <main>:	0x8955
(gdb) x/w 0x080484cf
0x80484cf <main>:	0x83e58955


해당 메모리 주소의 값을 각각 1바이트, 2바이트, 4바이트만큼 출력해주었습니다.

◎ GDB 사용법 9

  • x/x
    • 메모리 주소값을 16진수로 출력
  • x/u
    • 메모리 주소값을 10진수로 출력
(gdb) x/x 0x080484cf
0x80484cf <main>:	0x83e58955
(gdb) x/u 0x080484cf
0x80484cf <main>:	2212858197


해당 메모리 주소 값을 16진수, 10진수로 출력해주었습니다.

보통 아래와 같이들 씁니당!
(진법 옵션이든 바이트 옵션이든 생략되면 이전 옵션으로 실행해줍니다.)


(gdb) x/wx 0x080484e6
 0x80484e6 <main>: 0x83e58955
(gdb) x/4b 0x080484e6
 0x80484e6 <main>: 0x55 0x89 0xe5 0x83


값을 ebp 값에 저장하고 있죠?
esp, ebp는 스택과 관련한 레지스터잖아요!
그 메모리에 어떤 값이 담겨있는지 gdb로 확인해보도록 할게씀미당!

그 전에 메모리 출력 방식에 대해 정리하고 가도록 할게요.
몇 바이트만큼 그리고 몇 진법으로 출력할 것인지 정해 옵션을 주어 출력해주면 된다는거!


(gdb) x/wx 0x080484cf
0x80484cf <main>:	0x83e58955
(gdb) x/4b 0x080484cf
0x80484cf <main>:	0x55	0x89	0xe5	0x83


헙.. 근데 출력되는 순서가 조금 이상하죠?
4바이트 출력한 것과 1바이트씩 4개를 출력한 것과 순서가 반대예요!
바이트 오더링 개념에 대해 이해를 해야 합니다!


  • Byte Ordering - Little Endian & Big Endian
    • Intel CPU는 바이트를 배열할 때 거꾸로 쓰게 됩니다.
      예를 들어 0x12345678을 저장한다고 하면, 0x78563412와 같이 거꾸로 저장하게 됩니다.
      이런 방식을 Little Endian 이라 지칭합니다.
    • 반면, gdb는 디버깅 시에 보기 편하게 하기 위해서
    • Big Endian 형식으로 0x12345678와 같이 출력해주기 때문에,
      1바이트씩 출력할 때와 4바이트로 출력할 때 달리 보이는 거예요.
    • 참고로 네트워크 상에서는 Big Endian 형식의 바이트 오더링을 사용합니다.


특정 레지스터를 기준으로 메모리 값을 보고 싶거나, 레지스터의 정보를 보고 싶을 때는 아래와 같이 합니다.

(gdb)  x/4wx $esp
0xffffd230:	0x00000001	0x00000002	0x08048539	0x00000000


◎ GDB 사용법 10

  • $[레지스터 이름]
    • 레지스터를 기준으로 메모리 값을 출력


◎ GDB 사용법 11

  • info r
    • 레지스터의 정보를 출력


다음은 ebp와 esp를 출력 해 본 것이고,
레지스터의 정보를 출력 해 본 것입니당.


(gdb) x/wx $ebp
0xffffd248:	0x00000000
(gdb) x/wx $esp
0xffffd248:	0x00000000
(gdb) info reg $ebp
ebp            0xffffd248	0xffffd248
(gdb) i r $ebp $esp
ebp            0xffffd248	0xffffd248
esp            0xffffd248	0xffffd248
(gdb) i r
eax            0xf7fc2dbc	-134468164
ecx            0xc85e173	210100595
edx            0xffffd274	-11660
ebx            0x0	0
esp            0xffffd248	0xffffd248
ebp            0xffffd248	0xffffd248
esi            0xf7fc1000	-134475776
edi            0xf7fc1000	-134475776
eip            0x80484d2	0x80484d2 <main+3>
eflags         0x296	[ PF AF SF IF ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99


자.. 이제 gdb의 기본적인 사용법은 거진 다 익힌 것 같아요.

이제 우리 좀 더 알아가볼까요..?ㅎㅎ




2. 갖고싶다.. 너란 STACK..



현재 EIP 의 상황은 다음과 같아여. main 함수에서 인스트럭션 두 개를 실행했지여.


   0x080484cf <+0>:	    push   ebp
   0x080484d0 <+1>:	    mov    ebp,esp
=> 0x080484d2 <+3>:	    sub    esp,0x10
   0x080484d5 <+6>:	    mov    DWORD PTR [ebp-0x4],0x0
   0x080484dc <+13>:	push   0x2
   0x080484de <+15>:	push   0x1




2-1. Stack의 시작


$ push ebp

$ mov ebp, esp


단 두 줄의 인스트럭션만 실행이 되었기 때문에 별 거 없을 것 같지여?
하지만 저 단 두 줄의 어셈이 의미하는 바는 상당합니다.
바로 스택(프레임)이 생성 되기 때문이예여.


저 두 줄의 의미는

1. 함수가 실행이 될 때, 그 이전의 ebp(sfp)를 스택에 push하고

2. 현재 esp를 ebp에 저장하라.

입니다.
아직 어떤 데이터도 스택에 push 되지 않았기 때문에 espebp와 같겠지여!
이렇게 스택 프레임이 생성됩니다.




2-2. 스택을 보자!!


0x080484e0 <+17>:	call   0x80484ae <sum>   

여기에 브레이크포인트를 걸고 실행시킨 후의 스택의 상황을 보겠습니답.
breakpoint까지 한 번에 뛰려면 c 명령을 사용하면 됩니당.


(gdb) c
Continuing.

Breakpoint 1, 0x080484e0 in main ()
(gdb) disas main
Dump of assembler code for function main:
   0x080484cf <+0>:	    push   ebp
   0x080484d0 <+1>:	    mov    ebp,esp
   0x080484d2 <+3>:	    sub    esp,0x10
   0x080484d5 <+6>:	    mov    DWORD PTR [ebp-0x4],0x0
   0x080484dc <+13>:	push   0x2
   0x080484de <+15>:	push   0x1
=> 0x080484e0 <+17>:	call   0x80484ae <sum>
   0x080484e5 <+22>:	add    esp,0x8


원하는 곳에 멈춰잇쪄?

그럼 sum 함수가 call 되기 전의 상황과 후의 상황을 좀 볼까여?


sum이 call되기 전 상황

(gdb) i r $esp $ebp
esp            0xffffd230	0xffffd230
ebp            0xffffd248	0xffffd248
(gdb) x/8wx $esp
0xffffd230:	0x00000001	0x00000002	0x08048539	0x00000000
0xffffd240:	0xf7fc1000	0x00000000	0x00000000	0xf7e29637


그리고 sum 함수 안으로 들어가보도록 하겠습니다.
call을 할 때는 다음 인스트럭션의 주소를 스택에 쌓고 가죠?


   0x080484e0 <+17>:	call   0x80484ae <sum>
   0x080484e5 <+22>:	add    esp,0x8
   0x080484e8 <+25>:	mov    eax,DWORD PTR [ebp+0xc]  


call sum에 breakpoint를 걸고 sum 안으로 들어가면
스택에 ESP(0x00000001)위에 0x080484e5가 쌓였을 거예여!
확인해볼까욤?


sum이 call된 후의 상황

(gdb) x/16wx $esp
0xffffd22c:	0x080484e5	0x00000001	0x00000002	0x08048539
0xffffd23c:	0x00000000	0xf7fc1000	0x00000000	0x00000000
0xffffd24c:	0xf7e29637	0x00000002	0xffffd2e4	0xffffd2f0
0xffffd25c:	0x00000000	0x00000000	0x00000000	0xf7fc1000


sum 함수 안으로 들어가 보겠습니다.


◎ GDB 사용법 12

  • si
    • 함수 안으로 진입


(gdb) si
0x080484ae in sum ()
(gdb) disas sum
Dump of assembler code for function sum:
=> 0x080484ae <+0>:	    push   ebp
   0x080484af <+1>:	    mov    ebp,esp
   0x080484b1 <+3>:	    mov    edx,DWORD PTR [ebp+0x8]
   0x080484b4 <+6>:	    mov    eax,DWORD PTR [ebp+0xc]
   0x080484b7 <+9>:	    add    eax,edx
   0x080484b9 <+11>:	push   eax
   0x080484ba <+12>:	push   0x80485b8
   0x080484bf <+17>:	call   0x8048340 <printf@plt>
   0x080484c4 <+22>:	add    esp,0x8
   0x080484c7 <+25>:	call   0x804849b <func2>
   0x080484cc <+30>:	nop
   0x080484cd <+31>:	leave
   0x080484ce <+32>:	ret
End of assembler dump.


sum 함수 안으로 들어왔쪄? 오 역시나 Push ebp Mov ebp, esp 하고 있어욤!

Push ebp를 실행하면 그 이전 스택 프레임(main)의 ebp가 sum의 스택 프레임에 push 될거예여!
즉, main의 ebp 0xffffd248가 esp에 들어가겠쬬?


(gdb) ni
0x080484af in sum ()
(gdb) disas sum
Dump of assembler code for function sum:
   0x080484ae <+0>:	push   ebp
=> 0x080484af <+1>:	mov    ebp,esp
   0x080484b1 <+3>:	mov    edx,DWORD PTR [ebp+0x8]
   0x080484b4 <+6>:	mov    eax,DWORD PTR [ebp+0xc]
   0x080484b7 <+9>:	add    eax,edx
   0x080484b9 <+11>:	push   eax
   0x080484ba <+12>:	push   0x80485b8
   0x080484bf <+17>:	call   0x8048340 <printf@plt>
   0x080484c4 <+22>:	add    esp,0x8
   0x080484c7 <+25>:	call   0x804849b <func2>
   0x080484cc <+30>:	nop
   0x080484cd <+31>:	leave
   0x080484ce <+32>:	ret
End of assembler dump.
(gdb) x/x $esp
0xffffd228:	0xffffd248


오오… 마쟈마쟈ㅠㅠ
Mov ebp, esp를 하면 그리고 현재 esp를 sum stack frame의 바닥 즉, sum의 ebp로 만들어주겠져? 그러므로 sum의 ebp에는 main의 ebp가 있게되겠져!



이제 새로운 sum의 스택 프레임을 확인해볼까요?


(gdb) x/16wx $ebp
0xffffd158:	0xffffd178	0x080484e5	0x00000001	0x00000002
0xffffd168:	0x08048539	0x00000000	0xf7fc1000	0x00000000
0xffffd178:	0x00000000	0xf7e29637	0x00000002	0xffffd214
0xffffd188:	0xffffd220	0x00000000	0x00000000	0x00000000


이제 새로운 sum의 스택 프레임이 생성되었습니다!!
(현재 tomato.c에서 sum(1,2)라인이 실행 중이겠져?)

상단의 스택을 첫줄만 간추려보도록 하겠습니당!


0xffffd158:	0xffffd178	0x080484e5	0x00000001	0x00000002



보이심까?


새로운 스택 프레임의 ebp를 기준으로
return addressebp-4,
매개인자는 ebp-8, ebp -12와 같이 들어가게 됩니다!


꼭 기억하세욤!


자.. 또 sum 안에서 func2를 호출했어요!


(gdb) disas sum
Dump of assembler code for function sum:
   0x080484ae <+0>:	push   ebp
   0x080484af <+1>:	mov    ebp,esp
=> 0x080484b1 <+3>:	mov    edx,DWORD PTR [ebp+0x8]
   0x080484b4 <+6>:	mov    eax,DWORD PTR [ebp+0xc]
   0x080484b7 <+9>:	add    eax,edx
   0x080484b9 <+11>:	push   eax
   0x080484ba <+12>:	push   0x80485b8
   0x080484bf <+17>:	call   0x8048340 <printf@plt>
   0x080484c4 <+22>:	add    esp,0x8
   0x080484c7 <+25>:	call   0x804849b <func2>
   0x080484cc <+30>:	nop
   0x080484cd <+31>:	leave
   0x080484ce <+32>:	ret
End of assembler dump.
(gdb) b *sum+25
Breakpoint 3 at 0x80484c7
(gdb) c
Continuing.
sum : 3

Breakpoint 3, 0x080484c7 in sum ()
(gdb) disas sum
Dump of assembler code for function sum:
   0x080484ae <+0>:	push   ebp
   0x080484af <+1>:	mov    ebp,esp
   0x080484b1 <+3>:	mov    edx,DWORD PTR [ebp+0x8]
   0x080484b4 <+6>:	mov    eax,DWORD PTR [ebp+0xc]
   0x080484b7 <+9>:	add    eax,edx
   0x080484b9 <+11>:	push   eax
   0x080484ba <+12>:	push   0x80485b8
   0x080484bf <+17>:	call   0x8048340 <printf@plt>
   0x080484c4 <+22>:	add    esp,0x8
=> 0x080484c7 <+25>:	call   0x804849b <func2>
   0x080484cc <+30>:	nop
   0x080484cd <+31>:	leave
   0x080484ce <+32>:	ret
End of assembler dump.


그럼 아마 스택의 모습은 | func2 stack frame | sum stack frame | main stack frame|와 같이 되겠져?

확인해볼게염!!


(gdb) si
0x0804849b in func2 ()
(gdb) disas func2
Dump of assembler code for function func2:
=> 0x0804849b <+0>:	push   ebp
   0x0804849c <+1>:	mov    ebp,esp
   0x0804849e <+3>:	push   0x80485b0
   0x080484a3 <+8>:	call   0x8048360 <puts@plt>
   0x080484a8 <+13>:	add    esp,0x4
   0x080484ab <+16>:	nop
   0x080484ac <+17>:	leave
   0x080484ad <+18>:	ret
End of assembler dump.
(gdb) ni
0x0804849c in func2 ()
(gdb) ni
0x0804849e in func2 ()
(gdb) x/24wx $esp
0xffffd150:	0xffffd158	0x080484cc	0xffffd178	0x080484e5
0xffffd160:	0x00000001	0x00000002	0x08048539	0x00000000
0xffffd170:	0xf7fc1000	0x00000000	0x00000000	0xf7e29637
0xffffd180:	0x00000002	0xffffd214	0xffffd220	0x00000000
0xffffd190:	0x00000000	0x00000000	0xf7fc1000	0xf7ffdc04
0xffffd1a0:	0xf7ffd000	0x00000000	0xf7fc1000	0xf7fc1000

시작이 있으면 끝이 있겠져?
스택의프레임이시작되는 Push ebp,Mov ebp, esp를 자세히 살펴 보았으니

스택 프레임의 끝
Leave,Ret을 살펴보도록 하겠습니다.



2-3. 스택의 끝


$ leave

$ ret


◎ 현재 EIP의 위치


(gdb) disas func2
Dump of assembler code for function func2:
   0x0804849b <+0>:	push   ebp
   0x0804849c <+1>:	mov    ebp,esp
   0x0804849e <+3>:	push   0x80485b0
   0x080484a3 <+8>:	call   0x8048360 <puts@plt>
   0x080484a8 <+13>:	add    esp,0x4
   0x080484ab <+16>:	nop
=> 0x080484ac <+17>:	leave
   0x080484ad <+18>:	ret
End of assembler dump.


현재 eip는 leave 실행을 기다리고 있습니다!!


◎ 현재 leave 실행 전 스택 프레임 상황

(gdb) x/32wx $esp
0xffffd150:	0xffffd158	0x080484cc	0xffffd178	0x080484e5
0xffffd160:	0x00000001	0x00000002	0x08048539	0x00000000
0xffffd170:	0xf7fc1000	0x00000000	0x00000000	0xf7e29637
0xffffd180:	0x00000002	0xffffd214	0xffffd220	0x00000000
0xffffd190:	0x00000000	0x00000000	0xf7fc1000	0xf7ffdc04
0xffffd1a0:	0xf7ffd000	0x00000000	0xf7fc1000	0xf7fc1000
0xffffd1b0:	0x00000000	0x5d7d9f4f	0x67f5715f	0x00000000
0xffffd1c0:	0x00000000	0x00000000	0x00000002	0x080483a0


◎ leave 실행 후 스택 프레임 상황

(gdb) ni
0x080484ad in func2 ()
(gdb) disas func2
Dump of assembler code for function func2:
   0x0804849b <+0>:	push   ebp
   0x0804849c <+1>:	mov    ebp,esp
   0x0804849e <+3>:	push   0x80485b0
   0x080484a3 <+8>:	call   0x8048360 <puts@plt>
   0x080484a8 <+13>:	add    esp,0x4
   0x080484ab <+16>:	nop
   0x080484ac <+17>:	leave
=> 0x080484ad <+18>:	ret
End of assembler dump.
(gdb) x/32wx $esp
0xffffd154:	0x080484cc	0xffffd178	0x080484e5	0x00000001
0xffffd164:	0x00000002	0x08048539	0x00000000	0xf7fc1000
0xffffd174:	0x00000000	0x00000000	0xf7e29637	0x00000002
0xffffd184:	0xffffd214	0xffffd220	0x00000000	0x00000000
0xffffd194:	0x00000000	0xf7fc1000	0xf7ffdc04	0xf7ffd000
0xffffd1a4:	0x00000000	0xf7fc1000	0xf7fc1000	0x00000000
0xffffd1b4:	0x5d7d9f4f	0x67f5715f	0x00000000	0x00000000
0xffffd1c4:	0x00000000	0x00000002	0x080483a0	0x00000000


Leave 실행 후에 func2의 stack frame이 모두 정리된 것 보이시나여?!
그리고 ebpsumebp로 바뀌고 espsumesp로 바뀌었습니다.


(gdb) x/i 0x080484cc
   0x80484cc <sum+30>:	nop


그리고 Ret을 만나면 0x080484cc로 리턴해 나머지 sum의 인스트럭션을 실행하고,
끝으로 sum의 stack frame도 정리되고,
나머지 main의 인스트럭션을 실행한 후 프로그램을 종료되겠씀미다아아!!


쟈아아아 오늘은 gdb도 써보고 스택 프레임에 대해서도 자세히 알아보았눈데
어떠셔쎄여!!


다음 번엔 좀 더 다이나믹한 데이트를 합씨당!!
아 물론 데이트 코스는 제가 짭니당^ㅠ^




차회 예고

그럼 이만 뿅!!

comments powered by Disqus