본문 바로가기

Reverse Engineering

아이다(IDA)의 Debugging - Stack 분석

IDA의 디버깅을 통한 스택의 Stack 분석

분석해볼 프로그램은 IDA의 사용법을 알아보기 위해 예제로 썻던 것을 계속 쓰겠다.

다시 한번 설명하면 func( ) 함수에 세 개의 값을 파라미터로 전달하고 그 값들의 합을 리턴하는 프로그램이다.


#include <stdio.h>

 func(int a, int b, int c)
{
           return a+b+c;
}

int main(void)
{
           int sum;
           sum = func(1, 2, 3);
           return sum;
}


프로그램이 실행되기 전의 Stack이다. ESP, EBP의 위치를 살펴본다.


.text:00401060 push    ebp :
EBP가 가리키는 곳이 SFP(Saved Frame Pointer)로 변하고, 그 윗부분이 RET로 바뀌며 스택에 EBP값 12FFC0h값을 넣고 ESP는 한 칸 내려간다.
(참고 : EBP는 함수 시작전의 기준점이 되며. 이 최초의 EBP가 할당된 값을 스택에 저장한다. SFP(SavedFramePointer) : 스택에 저장된 EBP, RET : 함수 종료시 점프 할 주소 값을 저장)

.text:00401061 mov     ebp, esp :
EBP가 ESP가 가리키는 곳을 가리키게 된다. 즉 EBP와 ESP가 같은 지점을 가리킨다.

.text:00401063 sub     esp, 44h :
EBP가 가리키는 곳이 SFP로 변하고 바로 밑에 RET가 있다. 또한 ESP에서 44를 뺀다. 즉 ESP는 var_44변수를 가리키게 된다.

.text:00401066 push ebx :
ESP가 한 칸 내려가면서 현재 EBX값 7FFDA000이 스택에 들어간다.

.text:00401067 push    esi :
ESP가 한 칸 내려가면서 현재 ESI값 01B26D97이 스택에 들어간다.

.text:00401068 push    edi :
ESP가 한 칸 내려가면서 현재 EDI값 01B26CF8이 스택에 들어간다.
       
.text:00401069 lea     edi, [ebp+var_44] :
[ebp+var_44]의 주소를 EDI에 넣는다.

.text:0040106C mov     ecx, 11h :
11을 ECX에 넣는다.

.text:00401071 mov     eax, 0CCCCCCCCh :
CCCCCCCC를 EAX에 넣는다.

.text:00401076 rep stosd :
기본 할당 공간(ECX값 11)을 EAX값으로 채운다, EDI는 반복할 때마다 한 칸 올라간다.
                                    
.text:00401078 push    3 :
ESP가 한 칸 내려가면서 3값이 들어간다.
                       
.text:0040107A push    2 :
ESP가 한 칸 내려가면서 2값이 들어간다.

.text:0040107C push    1
ESP가 한 칸 내려가면서 1값이 들어간다.

.text:0040107E call    j_func :
j_func를 call한다.
call j_func의 내부로 추적해 들어가겠다.(Step Into)


stack

       .text:00401020 push    ebp :
       EBP가 가리키는 곳이 SFP(Saved Frame Pointer)로 변하고, 그 윗부분이 RET로
       바뀌며 ESP는 다음 주소를 가리킨다.

      .text:00401021 mov     ebp, esp :
      EBP가 ESP가 가리키는 곳을 가리킨다.

      .text:00401023 sub     esp, 40h :
       EBP가 가리키는 곳이 SFP로 변하고 바로 밑에 RET가 있다. 또한 ESP에서 40을
       뺀다. 즉 ESP는 var_40변수를 가리킨다.

      .text:00401026 push    ebx : 
      ESP가 한 칸 내려가면서 현재 EBX값 7FFDB000h이 스택에 들어간다.
      
      .text:00401027 push    esi :
      ESP가 한 칸 내려가면서 현재 ESI값 01B26D97이 스택에 들어간다.

      .text:00401028 push    edi :
      ESP가 한 칸 내려가면서 현재 EDI값 12FF80h이 스택에 들어간다.

      .text:00401029 lea     edi, [ebp+var_40] :
      [ebp+var_40]의 주소를 EDI에 넣는다.

      .text:0040102C mov     ecx, 10h :
      10을 ECX에 넣는다.

      .text:00401031 mov     eax, 0CCCCCCCCh :
      CCCCCCCC를 EAX에 넣는다.

      .text:00401036 rep stosd :
      기본 할당 공간(ECX값 10)을 EAX값으로 채운다, EDI는 반복할 때마다 한 칸 올라 간다.

      .text:00401038 mov     eax, [ebp+arg_0] :
      [ebp+arg_0]의 값인 1을 EAX에 넣는다.

      .text:0040103B add     eax, [ebp+arg_4] :
      [ebp+arg_4]의 값인 2를 EAX에 더한다. (EAX = 1+2 = 3)

      .text:0040103E add     eax, [ebp+arg_8] :
      [ebp+arg_8]의 값인 3을 EAX에 더한다. (EAX = 3+3 = 6)

      .text:00401041 pop     edi :
      스택의 값(0012FF80)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.

      .text:00401042 pop     esi :
      스택의 값(01B26D97)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.

      .text:00401043 pop     ebx :
      스택의 값(7FFDB000)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.
      
      .text:00401044 mov     esp, ebp :
      EBP가 ESP가 가리키는 곳을 가리킨다.

      .text:00401046 pop     ebp :
      스택의 값(12FF80h)을 꺼내서 EBP에 넣는다. ESP는 한칸 내려간다.

      .text:00401047 retn :
      ESP는 한칸 위를 가리킨다.


.text:00401083 add     esp, 0Ch :
ESP에 0Ch를 더한다.

.text:00401086 mov     [ebp+var_4], eax :
EAX의 값인 6을 ebp+4에 위치에 넣는다.

.text:00401089 mov     eax, [ebp+var_4] :
의미없는 명령으로 ebp+4의 값인 6을 eax에 넣는다.

.text:0040108C pop     edi :
스택의 값(01B26CF8)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.

.text:0040108D pop     esi :
스택의 값(01B26D97)을 꺼내서 ESI에 넣는다. ESP는 한칸 내려간다.

.text:0040108E pop     ebx :
스택의 값(7FFDB000)을 꺼내서 EBX에 넣는다. ESP는 한칸 내려간다.

.text:0040108F add     esp, 44h :
ESP에 44를 더한다. EBP가 가리키는 곳을 가리킨다.

.text:00401092 cmp     ebp, esp :
EBP와 ESP값을 비교한다. (값이 같다)

.text:00401094 call    __chkesp :
__chkesp를 call한다.
건너뛰겠다.(StepOver)

.text:00401099 mov     esp, ebp :
EBP의 주소를 ESP에 넣게 되어 ESP는 현재의 EBP주소를 가리킨다.

.text:0040109B pop     ebp :
EBP는 이전의 EBP인 12FFC0h을 가리키게 되고 ESP는 한칸 내려간다.

.text:0040109C retn :
ESP가 가리키는 4011D9h주소로 이동하고(call명령 다음의 코드) ESP는 한칸 위를 가리킨다.
(참고 : 즉 처음 EBP값을 스택에 넣어 함수의 시작주소를 저장하고 RET로 함수가 끝난 후 메인루틴의 call 함수 다음의 코드로 리턴하여 메인루틴을 실행한다)