블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아

카테고리

분류 전체보기 (176)
잡담 (1)
IT 기기-리뷰&뉴스 (7)
리뷰 - 도서 (1)
리뷰 - 영상 (0)
리뷰 - 그림/음악 (1)
내장형 하드웨어 (163)
Total630,089
Today168
Yesterday195

 

 

rett

 

test 함수

D=4

 

C=3

 

 

 

 

A

 

B

main의 stack

 

 

 

← esp: main

 

 

B

 

← ebp: main

A

 

 

init

 


main에서 test 호출

인자 2개인 경우 stack에 푸쉬

test(4,3);

1. push 3

2. push 4

3. call test → 1) push eip  2) eip = &test

( 1),2)는 실제 코드는 아니고 이런 동작을 한다는 것을 보여주며 실제 코드는 1. 2. 3. 번이다.)


visual studio로 디버그

F5 debug → view → register

⇒ EIP, ESP, EBP를 추적한다.

 


⇒ EIP : 004010748

⇒ ESP : 0012FF84 → 0012FF7C

⇒ EBP : 0012FFC0 → 0012FF80

&A → 0x0012ff7C

&C → 0x0012ff74

main → 0x00401020 main(void)


- disassembly를 하면

main 함수

00401020 main → 55 8B EC 83

        push ebp → 55가 나온다. (401020 → main 주소와 같다.)

        move ebp, esp → 8B EC가 나온다. (401021)

        sub esp,50h → esp-50이란 뜻(sub는 마이너스의 의미)이며 3byte 차지(401023)

※ disassembly에서 소스위에 있는 기계어들을 init 함수라 하며 main함수가 호출하는 것으로 확인할 수 있듯이 제일 처음 실행된다.(엔트리 포인트 - 진입점)


test2 함수

004010B0 test2 → 55 8B EC 83

        push ebp → 55가 나온다. (4010B0 → main 주소와 같다.)

        move ebp, esp → 8B EC가 나온다. (4010B3)

        sub esp,50h → esp-40이란 뜻(sub는 마이너스의 의미)이며 3byte 차지(4010B6)


main 함수 분석

 

⇒ int A=1;

 00401038 mov   dword ptr[ebp-4], 1

 dword → double word (처음에 word는 16bit였다. 즉, double word는 4byte)

 ptr → pointer

 ebp → 주소(0012FF80)이며 즉, ebp - 4 = 0012FF80 -4 = 0015FF7C (&A의 주소값)


ptr[ebp -4]는 *0012FF7C =1; 이며 이것은 &A자리에 1을 넣으라(move)는 뜻

※ mov → 이동하다.(대입연산자)

ebp = esp →(어셈블리로 만들면) mov ebp, esp 

 

 

20

ret

 

test 함수

24

D=4

 

12FF28

C=3

2C

 

 

main stack ebp(old ebp)

 

RET

 

A

 

B

main의 stack

(12칸)

 

 

 

 

← esp: main

 

 

B

 

 

A

 

12FF80

stack ebp

RET(retrurn address)

 

init

← ebp: main

 

 

 



※ visual C는 컴파일 할때 main 함수 영역에 ebp 와 esp가 동일선상에 있지 않고 변수가 적다면 esp가 48byte 만큼(12칸) 올라가 있다. 만약 변수가 A와 B 두 개라면 A와 B 위에 10칸을 남겨두고 esp는 위치해 있는 것.


 

- ebp는 항상 변수의 주소값의 기준이다.

- init의 위로 main 함수가 push되면 esp가 올라오며 ebp값을 끌어 올린다.




 

[disassmble]

--- d:\linux 공유폴더\20110428_stackview\main.c  ------------------------

1:    #include <stdio.h>

2:

3:    void test(int A, int B);

4:    void test2();

5:

6:    int main()

7:    {

00401030   push        ebp /* init에 있는 ebp값을 main 함수 아래에 놓는다.(이곳에는 ebp 값이 저장되어 있고 나중에 return address 를 통해 ebp가 반환된다.) */

00401031   mov         ebp,esp // ebp에 esp를 대입한다.

00401033   sub         esp,4Ch /* esp에 4C 만큼을 뺀다. 이것은 visual C에서 임의로 main 함수의 간격을 정한 것으로 esp는 4C만큼 주소값이 작아져 stack의 위쪽으로 올라간다. main함수의 시작에서 올라간 esp만큼을 main 함수의 stack 이라 한다. push부터 sub까지의 3개의 코드를 Ent교 code라 한다.*/

00401036   push        ebx

00401037   push        esi

00401038   push        edi

00401039   lea         edi,[ebp-4Ch]

0040103C   mov        ecx,13h

00401041   mov        eax,0CCCCCCCCh

00401046   rep stos    dword ptr [edi]

8:        int A=1;

00401048   mov         dword ptr [ebp-4],1 /* dword는 double word를 말하는 것으로 여기서 word는 16bit 컴퓨터의 개념인 2byte로 총 4byte를 말한다. ptr은 pointer의 의미이며 ebp의 값인 0012FF80에서 4를 뺀 것으로 0012FF7C가 되어 이것은 A의 주소가 되며 ,1은 &A의 자리에 1을 대입하라는 뜻이다. */

9:        int B=2;

0040104F   mov         dword ptr [ebp-8],2  /* 0012FF78의 주소에 B가 생성되어 2가 대입되었다.*/

10:       unsigned char *P = (unsigned char *)&B;

00401056   lea         eax,[ebp-8]

00401059   mov         dword ptr [ebp-0Ch],eax

11:

12:       printf("&main(): %08X\n&test(): %08X\n\n", main, test);

0040105C   push        offset @ILT+10(_test) (0040100f)

00401061   push        offset @ILT+5(_main) (0040100a)

00401066   push        offset string "&main(): %08X\n&test(): %08X\n\n" (00420054)

0040106B   call        printf (004012b0)

00401070   add         esp,0Ch

13:       printf("&A: %08X\n&B: %08X\n\n", &A, &B);

00401073   lea         ecx,[ebp-8]

00401076   push        ecx

00401077   lea         edx,[ebp-4]

0040107A   push        edx

0040107B   push        offset string "&A: %08X\n&B: %08X\n\n" (0042003c)

00401080   call        printf (004012b0)

00401085   add         esp,0Ch

14:       printf(" B: %02X %02X %02X %02X\n\n", *P, *(P+1), *(P+2), *(P+3));

00401088   mov         eax,dword ptr [ebp-0Ch]

0040108B   xor         ecx,ecx

0040108D   mov         cl,byte ptr [eax+3]

00401090   push        ecx

00401091   mov         edx,dword ptr [ebp-0Ch]

00401094   xor         eax,eax

00401096   mov         al,byte ptr [edx+2]

00401099   push        eax

0040109A   mov         ecx,dword ptr [ebp-0Ch]

0040109D   xor         edx,edx

0040109F   mov         dl,byte ptr [ecx+1]

004010A2   push        edx

004010A3   mov         eax,dword ptr [ebp-0Ch]

004010A6   xor         ecx,ecx

004010A8   mov         cl,byte ptr [eax]

004010AA   push        ecx

004010AB   push        offset string " B: %02X %02X %02X %02X\n\n" (0042001c)

004010B0   call        printf (004012b0)

004010B5   add         esp,14h

15:

16:       test(4, 3);

004010B8   push        3 // stack 3을 넣는다.

004010BA   push        4 // stack 4를 넣는다.

004010BC   call        @ILT+10(_test) (0040100f) /* ① push eip(→instruction pointer) ② eip =&test

004010C1   add         esp,8

17:       test2();

004010C4   call        @ILT+0(_test2) (00401005)

18:

19:       return 0;

004010C9   xor         eax,eax

20:   }

004010CB   pop         edi

004010CC   pop         esi

004010CD   pop         ebx

004010CE   add         esp,4Ch

004010D1   cmp         ebp,esp

004010D3   call        __chkesp (00401330) /* 10CB부터 여기까지는 해킹을 방지하기 위해 visual studio 에서 자동으로 삽입하는 것. */

004010D8   mov         esp,ebp /* ebp를 esp에 대입한다. 즉, esp의 위치를 원상복구 시킨다. */

004010DA   pop         ebp // ebp를 삽입한다.① eip = *esp, ② esp =eip+4

004010DB   ret


⇒ move ebp, esp → ebp = esp

   sub esp,50h → esp = esp-0x50

   ret

 → 위의 3개의 코드를 exit code라하고 우리가 C 소스에서 return ;을 하면 삽입된다.

⇒ stack과 stack 사이에는 return address, 인자, main ebp 등이 있다.

Posted by 동화다아아

댓글을 달아 주세요

최근에 달린 댓글

최근에 받은 트랙백

글 보관함