>> 소스코드
>> 메모리 구조
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 |