IT/Wargame

[System Hacking] out_of_bound

kykyky 2024. 7. 10. 14:50

>> 소스코드

 

>> 메모리 구조

 

higher..

 

--stack--

 

Return address

old EBP [ebp]

push ecx [ebp - 4]

? [ebp - 8]

? [ebp - 12]

idx값 [ebp - 16]

 

-- stack--

 

name

command

 

lower..

 

Q. idx의 주소는 어떻게 알았는가?

A.

소스 코드를 보면 idx는 scanf()의 두번째 argument로 입력되므로,

어셈블리에서 scanf()가 호출되기 전 부분을 보고, 그 순간에 stack에 push되는 걸 보자.

   0x08048723 <+88>:    lea    eax, [ebp-0x10]
   0x08048726 <+91>:    push   eax
   0x08048727 <+92>:    push   0x8048832
   0x0804872c <+97>:    call   0x8048540 <__isoc99_scanf@plt>

즉, ebp - 0x10이라는 주소값을 eax를 통해 push한 뒤, 0x8048832을 push한다.

따라서, idx의 주소는 ebp - 0x10이다. 

 

Q. name의 주소는 어떻게 알았는가?

A.

소스 코드를 보면 name는 read()의 두번째 argument로 입력되므로,
어셈블리에서 read()가 호출되기 전 부분을 보고, 그 순간에 stack에 push되는 걸 보자.

   0x080486ff <+52>:    push   0x10
   0x08048701 <+54>:    push   0x804a0ac
   0x08048706 <+59>:    push   0x0
   0x08048708 <+61>:    call   0x80484a0 <read@plt>

name의 주소는 0x804a0ac이다.

 

Q. command의 주소는 어떻게 알았는가?

A.

소스 코드를 보면 command는 system()의 argument로 입력되므로,
어셈블리에서 system()가 호출되기 전 부분을 보고, 그 순간에 stack에 push되는 걸 보자

   0x08048734 <+105>:   mov    eax,DWORD PTR [ebp-0x10]
   0x08048737 <+108>:   mov    eax,DWORD PTR [eax*4+0x804a060]
   0x0804873e <+115>:   sub    esp,0xc
   0x08048741 <+118>:   push   eax

아까 ebp - 0x10은 idx임을 확인했다.

+105에서는 eax에 idx값을 넣는다.

그럼 추측해보면 +108의 0x804a060은 command의 주소이고,

[eax*4+0x804a060]은 (command의 주소 + idx값 * 4)이 가리키는 값 인 것이다.

※ eax에 4를 곱한 이유

: command 배열 한 요소의 크기 = (char *)의 크기 = 32바이트 architecture에서는 4바이트

이므로 4를 곱함.

 

>> exploit

 

system()에는 command[idx]이 전달되므로,

공격자는 command[idx] == "/bin/sh" 주소가 되도록 만들어야 하며,

"/bin/sh"가 메모리의 어딘가에 적재되어야 한다.

 

그럼, 공격자가 임의 string을 넣을 수 있는 곳을 알아보자.

그건 바로 name 변수이다.  

 

여기다 넣은 임의 값을 command[idx]로 어떻게 활용하는가?: 

name의 주소 - command의 주소 = 0x4c = 4 * 19이다.

즉, command의 주소 + 19 * 4 = name의 주소 

즉, command[19] = name[0]이다.

 

1.  name에 b"/bin/sh\x00"을 입력한다. 

 

※ \x00을 넣은 이유

/bin/sh는 총 7바이트이고,

\x00으로 1바이트를 추가함으로써 4바이트 단위로 맞춰준 것이다.

 

4바이트로 맞춘 이유는,

command array의 인덱싱이 4바이트 단위로 되기 때문이다.

 

4바이트 단위로 인덱싱되는 이유는,

command array의 요소 하나하나가 (char *), 즉 포인터라서 4바이트이기 때문이다.

 

2. 그 뒤에 name의 주소, 즉 0x0804a0ac을 넣는다.

 

여기까지 하면 name 부분의 메모리는 아래와 같이 된다:

 

higher..

 

0x0804a0ac (4바이트) <- command[21]

/bin/sh\x00 (8바이트) <- command[19]

 

lower..

 

3. "/bin/sh"의 주소를 인덱싱하기 위해 idx = 21을 넣어준다.

 

위를 구현한 최종 exploit 코드는 아래와 같다:

 

아래는 똑같은 원리로 아주 조금만 바꾼 코드이고, 이것도 동작한다.

(payload에서 "/bin/sh"와 주소값의 자리를 바꿈)

 

'IT > Wargame' 카테고리의 다른 글

[Web hacking] bob12-idor-practice  (0) 2024.07.24
[Web Hacking] file-download-1  (0) 2024.07.09
[Web Hacking] image-storage  (0) 2024.07.08
[Web Hacking] command-injection-1  (2) 2024.07.08
[Web Hacking] Mango  (0) 2024.07.07