FTZ Level 16

bin3635·2021년 8월 10일
0

hint는 다음과 같다.

이번에는 함수가 3개다. main 함수를 보면 call이라는 void형 포인터에 printit 함수의 주소를 넣고, fgets 함수가 실행된 이후에 호출하는 것을 볼 수 있다.
20바이트의 buf에 48바이트만큼의 입력을 허용하고 있기 때문에 버퍼 오버플로우가 발생할 수 있다.
shell 함수는 Level 17의 쉘을 부여하는 함수이지만, 어디에서도 호출되고 있지 않다.

그렇다면 call 포인터의 값을 shell 함수의 시작 주소로 변조하면 되지 않을까?

이번에도 포인터를 사용하기 때문에 직접 gdb로 뜯어 보자.

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

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

<main+39>를 보면 call이 하나 더 있는데, 바로 윗줄에서 [ebp-16]을 eax에 넣었고, <main+6>에서 0x8048500을 [ebp-16]에 넣었다. 그렇다면 printit의 시작 주소가 0x8048500이라면? printit 함수가 [ebp-16]에 위치한다는 것이 된다.

printit 함수를 뜯어 보자.

예상대로, printit 함수의 시작 주소는 0x08048500이다. 즉 printit이 [ebp-16]에서 호출된다는 것도 알 수 있다.

이 주소를 shell 함수의 시작 주소로 바꿔야 한다.
shell 함수를 뜯어 보자.

shell 함수의 시작 주소는 0x080484d0이다.

스택의 구조는 다음과 같다.

위 그림에 따르면, call 바로 전까지의 40바이트를 의미 없는 문자로 채우고 남은 4바이트를 shell 함수의 시작 주소로 채우면 된다.

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

(python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme

Level 17의 쉘을 얻었다.

0개의 댓글