2 분 소요

문제파악

image

소스 코드와 바이너리 모두 주어진 상태에서 시작을 하게 된다. 소스코드를 보면 어떻게든 실행 흐름을 바꿔서 system 함수를 호출하는 부분을 실행해라 라는 것이 정답이라는 것이 쉽게 드러난다. 그리고 바이너리를 실행해 보면 scanf를 잘못 사용하여 정상작동이 되지 않는다는 것을 확인할 수 있다. 변수의 주소값 대신 변수의 값을 인자로 넣게 되는 것을 위의 코드를 통해 확인할 수 있다. 이 부분을 이용해서 실행흐름을 바꾸라는 것이 이 문제의 의도로 보인다.

image

우의 welcome 함수를 살펴보면 login 함수가 호출되기 직전에 호출되며 scanf 함수를 통해 지역변수에 문자열을 입력받아 저장하는 것을 볼 수 있다. 프로그램이 정상 실행시에도 로그인 부분에 입력이 잘못된 메모리 접근으로 인해 오류가 뜨기 때문에 위의 코드 부분에서 무엇인가를 수행해야 하는 것은 확실하다.

그럼 어떤 걸 해야할까를 생각할 때 가장 큰 착각을 하게 됬다. scanf 함수를 사용했으니 오버플로우를 이용해 passcode 변수들을 덮으면 login 함수 실행시 아무 입력을 넣지 않아도 조건문을 통과하게 수정할 수 있겠구나라고 생각을 했다. 지식도 없고 너무 성급해 생각않고 해보고 보는 탓에 명확하게 오버플로우는 불가능하다는 것을 알려주는 저 %100s를 무시하고 넘어가게 됬었다. 뻘짓을 몇 시간을 하고나서야 확인하였다…

지식의 한계라고 판단을 하고 검색을 해본 결과, 이 문제는 GOT overwrite 기법을 활용한다는 것을 알 수 있었다.

GOT overwrite

GOT, PLT 등 GOT overwrite 기법을 이해하기 위한 내용은 정말 잘 정리된 블로그 포스트를 발견해 링크를 남긴다.

PLT와 GOT 자세히 알아보기.

간단하게 설명하자면 Dynamic linking을 활용하게 되면 프로그램을 실행할 때 공유 라이브러리에서 필요한 함수들의 주소를 새로 채워넣게 되는데 이러한 주소들의 테이블이 GOT 테이블이 되고 이 GOT 테이블 주소를 가르키는 것이 PLT가 된다. 위의 블로그에서는 이해를 위해 GOT 테이블을 어떻게 만드는지 이러한 과정이 잘 분석되 있지만 사실 공격을 수행할 때는 굳이 저런 이해 없이도 가능하다. 핵심은 GOT 테이블의 주소가 함수의 주소가 된다는 것이다. 결국 이 GOT 테이블을 수정할 수 있으면 특정 함수를 호출할 때 임의의 주소로 실행흐름을 수정할 수 있게된다. GOT overwrite 기법을 활용하기 위해서는 임의의 주소의 값을 원하는 값으로 바꿀 수 있어야 한다.

다시 문제로 돌아오면 그럼 이 문제는 어떻게 이게 가능한가를 생각해 보자. 핵심은 코드의 오류에 있다. 입력을 변수의 주소에 저장하는 것이 아니라 주소가 변수의 값이 되는 곳에 저장하게 된다. 즉, 변수의 값을 임의로 수정할 수 있다면 원하는 주소 어디든 입력값을 넣을 수 있게 된다. 우선적으로 passcode1, passcode2의 값을 수정할 수 있을지 확인해 봤다.

gdb를 통해 지역변수 namepasscode 변수들의 주소를 살펴보면, 각각 name의 주소에 +96, +100인 주소에 위치한다는 것을 볼 수 있다.

사실 아직 의문인 점이 있다. name은 사이즈가 100인 캐릭터 형 배열인데 어떻게 passcode1이 +96 주소에 위치하는 것일까… -> 내가 아주 똥멍청이였다.. 지역변수인데 당연히 함수가 끝나면 쓰이질 않으니.. 배울 게 많다..

welcome 함수에서 name 변수로 최대 100byte 까지의 입력을 받기 때문에 passcode1의 값을 임의로 수정할 수 있다는 것을 알 수 있다.

결론

결국 이 문제는 처음 입력을 통해 함수의 지역변수 값을 GOT 테이블 주소로 변경한 후 다음 입력 때 원하는 주소값을 입력하여 특정 함수가 실행 될 때 실행 흐름을 바꾸는 것으로 해결하게 된다. printf 함수의 주소를 변경했다.

(python -c 'print "A"*96 + "\x00\xa0\x04\x08"'; cat) | ./passcode

image

여기서 의문인 점이 printf 함수의 주소를 변경한 것인데 어떻게 마지막 줄에 “Now I can ~~”와 같은 출력문이 출력 될 수 있었는가…

댓글남기기