[해커스쿨_FTZ] level20
드디어 마지막 문제입니다.
attackme의 소스코드를 보면 배열의 크기를 80으로 선언하였지만 79바이트로 입력을 제한하였으므로 오버플로우가 불가합니다.
그러나 printf()애서 발생하는 포맷 스트링 버그로 리턴 값을 덮을 수 있습니다.
-------------------------
포맷 스트링 ?
포맷 스트링 익스플로잇은 프로그램을 충돌시키거나 악의적인 코드를 실행 시키는데 사용될 수 있다. 문제는 포맷팅을 수행하는 printf() 같은 특정한 C 함수들에서 검사되지 않은 사용자 입력을 포맷 스트링 파라미터로 사용하는 것으로부터 나온다. 악의적인 사용자는 %s와 %x 포맷 토큰들을 콜 스택 또는 메모리의 가능한 다른 위치의 데이터를 보이게 하는 데 사용할 수 있다. 또한 %n 포맷 토큰을 사용해서 임의적인 데이터를 임의적인 위치로 쓸 수 있는데, 이것은 printf() 와 비슷한 함수들이 많은 바이트들을 스택에 저장된 주소에 쓰게 한다.
-위키-
-------------------------
이렇게 attackme에 값을 넣어 4번째 %8x의 스트링에 임의의 값을 입력할 수 있음을 확인합시다.
(AAAA -> 0x41414141)
우선 attackme의 리턴 값의 주소를 알아봅시다.
gdb를 사용하려했지만 실행이 안되므로 .dtors(소멸자) 를 이용해 알아봅시다.
--------------
.dtors?
main함수가 종료될 때 실행되는 함수
--------------
objdump명령어로 .dtors의 주소를 알아옵니다.
.dtors의 주소 + 4 는 리턴 값의 주소입니다.
쉘 코드를 넣은 환경변수를 만들어줍니다.
환경변수의 주소를 알아옵니다.
%c 와 %n을 써야하므로 알아온 주소를 하위 주소와 상위 주소로 나누어 10진수로 변환해줍니다.
그 후 하위 주소 앞의 바이트(4+4+4+4+8+8+8)만큼 하위주소의 10진수 값에서 빼주고
상위 주소도 앞의 바이트만큼(하위주소의 크기) 상위주소에서 빼줍니다.
상위 주소 앞에 1이 붙은 이유는 그냥 계산하면 음수 값이 나오기 때문입니다.
구한 값을 토대로 페이로드를 작성하면 끝!
빠르게 lob로 넘어갑시다!