먼저 hint의 코드를 분석해보자.
main 함수가 정의되어 있고 char 유형의 80byte bleh가 선언되었다.
setreuid 함수를 사용하여 권한을 최종으로 바꾸어주며,
fgets 함수를 통해 표준입력으로 79byte 만큼의 내용을
bleh에 입력한다. 여기서 버퍼 오버플로우는 일어나지 않는다.
마지막으로 printf 함수로 이 내용을 출력하며 끝난다.
이번 코드는 버퍼 오버플로우 취약점은 발견되지 않지만
bleh를 출력하는 과정에서 유형을 지정해주지 않았으므로
포맷 스트링 버그 취약점을 활용하는 문제라고 추측할 수 있다.
gdb를 사용하여 main 함수를 분석하려 하였으나
Main의 symbol이 없다는 내용이 출력된다.
AAAA 문자를 입력하면 그대로 출력하고
%x를 뒤에 연달아 3개 까지 추가했을 때는 주소값을 출력한다.
마지막으로 %x를 4개 연달아 입력할 경우에는 “41414141”을 출력한다.
이를 통해 12byte의 dummy 값이 존재하는 것을 알 수 있다.
[ 메모리 구조 ]
RET // 4byte
SFP // 4byte
Bleh // 80byye
Dummy // 12byte
Printf
Objdump 명령어를 통해 __DTOP_LIST__의 주소값이 08049594임을 알 수 있다.
내가 이용하려고 하는 값은 4byte를 더한 08049598이다.
* 소멸자 심볼 중에서 실제 값을 변조해 흐름을 바꾸는 것은 __DTOP_END__
베쉬 쉘 권한을 얻을 수 있는 SHELLCODE를 환경변수로 미리 등록해 놓았다.
Test 코드를 작성하여 SHELLCODE의 주소값을 얻었다
SHELLCODE의 주소는 bffffbc7이다.
[ 페이로드 ]
4byte + 소멸자의 높은 주소 + 4byte + 소멸자의 낮은 주소 + %8x%8x%8x + %쉘코드 낮은 주소c%n + %쉘코드 높은 주소c%n
dummy의 값은 12byte이기 때문에 %8x를 3개 추가하여 이 값을 채웠다.
처음에 문제를 풀 때는 4byte 자리에 “A”를 채워 놨었다.
어찌 됐든 4byte를 채우면 되는 것 같은데 %n 지정자를 사용하여 %c에 의해 4byte가 상승하기 때문이다.
이렇게 4byte를 추가해 줘야 내가 원하는 주소값을 가르킬 수 있다.
쉘코드의 주소값 역시 높은 값과 낮은 갚으로 나눠서 넣어야 하는데
bffffbc7 -> (높은주소) 49151 / (낮은주소) 64455
낮은 주소는 앞에 입력한 4byte + 소멸자의 높은 주소 + 4byte + 소멸자의 낮은 주소 + %8x%8x%8x의 바이트 수를 빼서
64455 - 40 = 64415로 페이로드에 대입하고
높은 주소 값은 앞의 네자리 bfff에 2의 보수를 해 1bffff를 취하고 64455를 뺀 후에 50232 값을 페이로드에 대입한다.
2의 보수를 취한 이유는 49151의 값에 50232를 빼면 음수가 나오기 때문이다.