Write-Up/FTZ

FTZ: Level 9

NONE_31D 2019. 11. 12. 23:32

 

문제의 힌트를 보면 바로 소스코드를 보여준다. char형 배열을 두개 선언해주고, 40크기의 문자열을 표준 입력(키보드)로부터 입력받는다. 

 

이때 배열은 둘 다 10바이트인데 40바이트를 입력받으니, buf에 입력을 받아도 버퍼 오버플로우를 이용하여 buf2의 값을 임의로 수정할 수 있을 것이라 생각된다.

 

if문을 살펴보면, go와 buf2의 문자열을 앞 2글자만 비교하는데 즉 buf2에 go라는 문자열을 입력시키면 if문 안으로 진입할 수 있다. if문 안에서는 uid를 3010(level10의 권한)으로 변경시킨 상태에서 bash쉘을 띄운다. 즉, if문 안으로 들어가기만 하면 level10의 권한으로 쉘을 실행할 수 있는 것.

level10의 uid 확인

/usr/bin/bof 파일은 디버거를 할 수 없으므로, 동일 코드를 level9/tmp에 작성하기로 한다.

 

 

a.c 코드

>를 이용하여 비교적 편하게 코드를 옮겨 적었다.

 

gcc로 컴파일을 하고, gdb로 디버깅을 실행한다. 

 

set disassembly-flavor intel : intel 식으로 어셈블리 출력

disas main : main 함수부분 디스어셈블하여 출력

 

우리가 살펴봐야 할 부분은 다음과 같다.

1. fgets(buf, 40, stdin);
2. strncmp(buf2, "go", 2);

함수를 호출할 때, 인자는 오른쪽에서부터 스택에 쌓인다. 그렇기 때문에 fgets()의 경우, stdin, 40, buf의 순으로 스택에 들어오게 된다.

디스어셈블 된 코드에서 main+41을 확인하면 다음과 같이 40이 스택에 들어간 것을 알 수 있다. 그렇기 때문에 그 다음 줄인 main+43에 있는 ebp-40이 buf의 주소가 될 것이다.

fgets 함수 호출 과정

이번에는 strncmp를 살펴보자. main+58을 보면, 2가 스택에 들어간 것을 알 수 있다. 그렇기에 순차적으로 들어간다면, main+65에 있는 ebp-24가 buf2의 주소가 된다.

strncmp 함수 호출 과정

 

buf와 buf2의 정확한 주소는 모르지만, 대략적으로 다음과 같이 스택에 저장되어있다는 것은 알 수 있다. 두 배열 간 거리는 16바이트이다.

buf2에 "go"를 입력하기 위해서는 buf에 16바이트를 입력하고, 17바이트째부터 "go"를 입력해야 한다. 정확하게 입력하기 위해 파이썬 스크립트를 사용하기로 한다.

(python -c 'print "A"*16 + "go"'; cat) | /usr/bin/bof

간단히, A를 16번 나열하고 그 끝에 "go"를 붙인 문자열을 출력하고 이어서 해당 명령으로 인한 결과를 출력한다. (;cat의 역할) 그리고 |(파이프)를 통해 이 입력을 /usr/bin/bof라는 파일을 실행시키고 나서 넘긴다.

 

실행을 하면 다음과 같이 배쉬 쉘이 뜨고, level10권한으로 쉘이 돌아가는 것을 확인할 수 있다. 항상 그렇듯, my-pass 명령어로 패스워드를 확인하면 된다.

'Write-Up > FTZ' 카테고리의 다른 글

FTZ: Level11  (0) 2019.11.13
FTZ: Level 10 - writeup 수정중 (해결완료)  (0) 2019.11.12
FTZ: Level 8  (0) 2019.09.26
FTZ: Level 7  (0) 2019.09.26
FTZ: Level6  (0) 2019.09.26