본문 바로가기

드림핵

[드림핵 워게임] basic_exploitation_000

<문제>

 

<풀이>

먼저 주어진 문제파일을 다운로드한다.

basic_exploitation_000.c를 열어봤다.

 main 함수부터 살펴보면,

24행에서 0x80크기의 char 배열 buf 변수를 선언한다.

26행은 그냥 timeout을 걸어놓은 것으로, 취약점과는 관련이 없는 것 같다.

28행의 printf() 는 buf의 주소를 출력해준다.

29행의 scanf()가 취약점과 직접적으로 관련된 부분으로 보인다.

buf 변수에 141바이트 만큼 값을 입력하는데 buf의 크기인 0x80(십진수로 128)보다 크므로 overflow가 발생할 수 있다.

 

gdb를 이용해 바이너리를 분석해보자.

<+37>에서 scanf() 함수를 호출하기 전 스택 프레임 상태를 확인해보면,

<+28>에서 [ebp-0x80]의 주소를 eax가 가리키게  한다.

scanf()로 입력받은 값은 eax에 저장되므로 결과적으로 스택 프레임의 [ebp-0x80] 위치에 저장될 것이다.

 

여기까지 main함수의 스택 프레임 구조를 그려보면 다음과 같다.

문제에서 ebp, eax 등 32비트 체제를 쓰고 있으므로 SFP와 return address는 각각 8bytes가 아닌 4bytes를 차지하게 된다.

 

 

스택 프레임 구조를 파악했고 stack buffer overflow 취약점이 있다는 것을 알았으니

이제 공격 시나리오를 짜보자.

(1) buf의 초반부에 shell을 실행하는 셸코드를 삽입할 것이다.

이때 셸코드를 scanf()를 이용해 입력해야 하므로 scanf() 우회 셸코드로 입력해야 한다.

(2) return address는 buf의 주소로 overwrite할 것이다.

(3) 셸코드의 끝~return address 사이는 임의의 문자로 채울 것이다.

 

이렇게 하면 ret명령어가 실행될 때 buf의 첫부분으로 return하게 되고, 셸코드가 실행되어

셸을 획득할 수 있게 될 것이다.

 

이 공격 시나리오를 바탕으로 python을 이용해 익스플로잇 코드는 아래와 같이 작성했다.

7행의 shellcode는 scanf 우회 셸코드로 인터넷에서 찾아서 복붙했다.

\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80

 

9행부터 payload를 구성하는데

먼저 가장 앞부분에 shellcode를 입력한다.

그 다음 buf의 크기인 128에서 shellcode길이만큼을 빼고 SFP의 길이인 4를 더해준 크기만큼 'A'문자로 채운다.

마지막에는 return address 값인 buf의 주소를 패킹한 값을 더해준다.

buf의 주소는 5행에서 구했는데, printf로 출력된 값에서 buf의 주소를 추출했다.

 

이렇게 만든 파이썬 파일을 실행하면 셸을 획득할 수 있다.

 

이제 로컬이 아닌 실제 서버를 대상으로 진짜 익스플로잇을 해볼 것이다.

먼저 process() 함수대신 4행과 같이 remote() 함수로 객체를 생성한다.

Host와 Port는 드림핵 문제 페이지에서 RequestVM을 클릭해서 받았다.

 

수정한 파이썬 파일을 실행하면 셸을 획득할 수 있고

ls를 입력해서 파일을 출력해보면 flag 파일이 있는 것을 확인할 수 있다.

cat flag

명령어로 파일 내용을 출력해보면 flag가 뜬다.