OverTheWire_Wargame Narnia

[ level3 -> level4 ]




Level3의 문제입니다.

R/W 권한과 READ ONLY의 권한으로 파일을 각각 하나씩 open 해줍니다.

output 하는 경로의 경우 "/dev/null"로 고정이 되어있네요. input의 경우에는 사용자에게 직접 입력을 받습니다. 이 때, 입력은 argv[1]로 받으며 strcpy 함수를 이용하기 때문에 길이 제한이 없습니다. 따라서 이 때 BOF가 발생하게 되는데, ofile은 값을 지정해줬음에도 불구하고 ifile보다 먼저 선언되었기 때문에 ifile에서 32바이트를 넘어가는 길이의 입력을 받을 경우 ofile의 값에도 영향을 미치게 됩니다.

이러한 스택의 특성을 이용하여 level4로 갈 수 있는 패스워드를 따 보도록 합시다.

일단 ifile의 경우 overflow를 시키면 ofile의 값을 덮어씌우게 되는데, 이럴 경우 ofile의 포인터는 overflow 된 ifile의 중간에 위치하게 됩니다. 따라서 아래와 같은 payload를 사용하면 두 개의 파일에 따로따로 접근 할 수 있게 됩니다.




ifle과 ofile을 이어 붙인 그림입니다.

입력을 받을 수 있는 argv[1]에는 ///////////////////tmp/fstr3am_/tmp/fstr3am_/a 를 넣어줍니다.

그럼 첫 번째 fstr3am_ 이후의 위치가 원래 ofile의 시작 포인터입니다. 따라서 ofile을 끄집어 낼 경우 /tmp/fstr3am_/a가 딸려나오게 됩니다.

그리고 ifile을 꺼낼 경우 원래 ifile의 길이인 24byte를 초과했기 때문에 ofile의 마지막인 a 이후에 나오는 NULL Byte까지 인식을 하여 /tmp/fstr3am_/tmp/fstr3am_/a이 ifile의 전체 경로가 됩니다.

그렇다면 /tmp/fstr3am_/tmp/fstr3am_/ 의 경로에 /etc/narnia_pass/narnia4의 symbolic link를 걸어준 a라는 이름의 파일을 생성해주고, /tmp/fstr3am_/ 의 경로에 비어있는 a라는 파일을 하나 만들어주면 /tmp/fstr3am_/a에 level4로 통하는 패스워드가 복사 될 것입니다.



위와 같이 a라는 파일을 두 개 만들어줍니다.



그리고 위에서 설명했던 payload대로 입력을 해 주면 패스워드가 출력됩니다.

OverTheWire_Wargame Leviathan

[ level5 -> level6 ]




자, 벌써 level5입니다. 홈 디렉토리를 확인하니 leviathan5라는 바이너리가 딱 버티고 있습니다.

권한을 확인 해 보니 이번에도 setuid bit가 걸려있네요. leviathan6 권한으로 실행이 되나봅니다. 파일을 실행 해 보니 "Cannot find /tmp/file.log"라는 오류 메시지를 내뱉고 프로그램을 종료시킵니다. 어떤 이유인지 확인하기 위해 gdb로 까보도록 하죠.



main 함수를 disassemble 한 상태입니다. 맨 처음에 fopen으로 파일 하나를 오픈 한 후, 해당 파일이 없으면 오류메시지를 내뱉고 프로그램을 종료시킵니다.

만약 파일이 있을 경우에는 fgetc와 feof 함수를 이용해 파일의 끝까지 이동하면서 한 바이트씩 읽어가며, 도중 putchar을 이용해 읽었던 값을 출력해줍니다.

그리고 eof에 도달하면 반복을 종료하고, getuid, setuid 함수를 이용해 현재 함수의 uid를 얻어와 setuid시키며 0x8048722에 들어있는 문자열을 인자로 unlink합니다.

fopen 할 때 인자로 전달하는 값 중 첫 번째 인자와 unlink 할 때 전달하는 인자가 동일합니다. 즉, fopen 하는 파일은 이 프로그램을 실행시키고 끝까지 실행됨과 동시에 삭제가 된다는 소리가 되겠네요.

상수 값을 분석해 본 결과, fopen의 두 번째 인자는 "r", 첫 번째 인자는 "/tmp/file.log"였습니다. 따라서 /tmp/file.log 파일을 읽어서 fgetc로 한 글자씩 저장하고, 출력하는 행위를 eof를 만날 때 까지 한다는 소리가 되겠네요.

그렇다면 /etc/leviathan_pass/leviathan6를 /tmp/file.log에 심볼릭 링크하여 leviathan5 프로그램을 실행시키면 해결 될 것 같습니다.



leviathan6로 통하는 패스워드를 아름답게 내뱉어주네요.

+ Recent posts