SH1R0_HACKER

stack 1 본문

System2/Protostar

stack 1

SH1R0_HACKER 2020. 10. 18. 15:49

 

Stack1.c

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}

 

코드를 분석해보면 main 함수에 argc와 argv가 전달된다.

사용자로부터 argument를 받아서 실해오디는 루틴을 가지고 있다.

 

modified를 0x61626364로 바꿔버리면 우리가 원하는 답을 얻을 수 있을 것 같다.


[ 취약점 파악 및 분석 ]

아래는 어셈블리어 해석이다.

   0x08048464 <+0>:     push   ebp
   0x08048465 <+1>:     mov    ebp,esp
   0x08048467 <+3>:     and    esp,0xfffffff0
   //새로운 스택 프레임 생성
   0x0804846a <+6>:     sub    esp,0x60
   //main 함수가 사용할 스택공간을 0x60만큼 할당
   0x0804846d <+9>:     cmp    DWORD PTR [ebp+0x8],0x1
   //[ebp+0x8]과 0x1을 비교한다.
   //argc 변수 : ebp+0x8
   0x08048471 <+13>:    jne    0x8048487 <main+35>
   //Jump not Equal 같지 않다면 main+35로 이동한다.
   0x08048473 <+15>:    mov    DWORD PTR [esp+0x4],0x80485a0
   // "please specify an argument"
   0x0804847b <+23>:    mov    DWORD PTR [esp],0x1
   0x08048482 <+30>:    call   0x8048388 <errx@plt>
   0x08048487 <+35>:    mov    DWORD PTR [esp+0x5c],0x0
   // [esp+0x5c]에 0을 저장한다.
   // modified 변수 : esp+0x5c
   0x0804848f <+43>:    mov    eax,DWORD PTR [ebp+0xc]
   // argv[1] : ebp+0xc
   0x08048492 <+46>:    add    eax,0x4
   0x08048495 <+49>:    mov    eax,DWORD PTR [eax]
   0x08048497 <+51>:    mov    DWORD PTR [esp+0x4],eax
   0x0804849b <+55>:    lea    eax,[esp+0x1c]
   // buffer 변수 : esp+0x1c
   0x0804849f <+59>:    mov    DWORD PTR [esp],eax
   0x080484a2 <+62>:    call   0x8048368 <strcpy@plt>
   0x080484a7 <+67>:    mov    eax,DWORD PTR [esp+0x5c]
   // eax 레지스터에 modified 변수[esp+0x5c]를 전달한다.
   0x080484ab <+71>:    cmp    eax,0x61626364
   0x080484b0 <+76>:    jne    0x80484c0 <main+92>
   0x080484b2 <+78>:    mov    DWORD PTR [esp],0x80485bc
   // "you have correctly got the variable to the right value"
   0x080484b9 <+85>:    call   0x8048398 <puts@plt>
   0x080484be <+90>:    jmp    0x80484d5 <main+113>
   0x080484c0 <+92>:    mov    edx,DWORD PTR [esp+0x5c]
   0x080484c4 <+96>:    mov    eax,0x80485f3
   // "Try again, you got 0x%08x\n"
   0x080484c9 <+101>:   mov    DWORD PTR [esp+0x4],edx
   0x080484cd <+105>:   mov    DWORD PTR [esp],eax
   0x080484d0 <+108>:   call   0x8048378 <printf@plt>
   0x080484d5 <+113>:   leave  
   0x080484d6 <+114>:   ret

 

argv의 위치 : ebp+0x8

modified의 위치 : esp+0x5c

buffer의 위치 : esp+0x1c

 

stack0와 비슷하게 buffer을 가득 채우고 modified를 0x61626364로 수정하면 될 것 같다.

HEX to String을 이용하면

0x61 = a

0x62 = b

0x63 = c

0x64 = d

라는 사실을 알 수 있다.


[ Exploit ]

 

buffer을 다 채우기 위해 64개의 문자열 A를 생성한다.

그 뒤에 modified 변수에 들어갈 abcd를 입력해준다.

그런데 Try again, you got 0x64636261 이라는 메시지가 보인다.

우리가 넣어야 할 값은 0x61626364인데 거꾸로 입력이 된 모습을 볼 수 있다.

그 이유는 인텔 CPU가 메모리를 읽고 쓰는 바이트 오더가 리틀엔디안 방식이기 때문이다.

 

바이트오더에는 두 가지 방식이 있다.

리틀 엔디안 (Little Endian) : 메모리 시작 주소가 하위 바이트부터 기록된다. intel 프로세서 계열에서 사용한다.

빅 엔디안 (Big Endian) : 메모리 시작 주소가 상위 바이트부터 기록된다. 주로 UNIX, 시스템인 RISC 프로세서 계열에서 사용한다.

 

결국 abcd를 그대로 입력하는 것이 아니라 역순으로 입력해야된다.

'System2 > Protostar' 카테고리의 다른 글

stack5  (0) 2020.10.18
stack 4  (0) 2020.10.18
stack 3  (0) 2020.10.18
stack 2  (0) 2020.10.18
Stack 0  (0) 2020.10.18