문제분석 & 풀이
코드 분석
1) i, buf[1024]를 선언
2) setreuid()를 통해 level14의 권한으로 설정
3) argv[1]을 통해 입력받은 값을 buf에 복사
4) 만약, i의 값이 바뀔 경우 BOF로 간주하고 프로그램 강제종료
이전 문제와 다른점은 변수 i를 통해 BOF가 발생하는지 안하는지를 체크하고 있다는 점이다.
이것을 우회하기 위해 변수 i가 바뀌지 않는 선에서 페이로드를 만들어서 BOF를 진행해야 할 것 같다.
attackme를 tmp 폴더로 복사하여 GDB로 디버깅했다.
main 시작 후에 0x418 만큼 스택공간을 할당한다.
0x418 = 1048임으로 [buf 1024바이트] + [더미 24바이트]가 포함됐다는 것을 알 수 있다.
그러나 더미 24바이트안에는 변수 i의 공간도 포함되어있음으로 변수 i의 시작주소를 알아내야한다.
하늘색 박스를 보면 0x1234567을 ebp-12 주소에 옮기는 것을 확인 할 수 있다. (0xfffffff4는 -12를 의미한다.)
C 코드에서 봤듯이 0x1234567은 변수 i의 값으로 ebp-12가 변수 i의 시작주소임을 알 수 있다.
위 정보들을 토대로 스택을 표현하면 다음과 같다.
buf부터 i까지 1036 바이트, 이후 i(4 바이트)와 dummy(8 바이트), SFP(4 바이트)까지 합한 값이 RET까지의 거리이다.
RET까지의 거리 : 1036+4+8+4=1052 바이트
이를 토대로 페이로드를 작성하면 다음과 같다.
"A"*1036+"0x1234567"+"A"*12+[셸코드 주소]
이제 셸코드를 적재하고 주소를 구해보자.
eggshell을 이용해서 환경변수에 셸코드를 적재했고 realaddr을 통해 주소를 구해보니 0xbffff2ea가 나왔다.
셸코드의 주소를 알아냈으니 페이로드를 완성해보자.
./attackme `python -c 'print "A"*1036+"\x67\x45\x23\x01"+"A"*12+"\xea\xf2\xff\xbf"'`
이제 완성한 페이로드를 이용하여 attackme를 실행해보자.
실행결과 위와 같이 셸이 떴다.
id 명령으로 권한을 확인해보니 level14의 권한임을 확인 할 수 있다.
마지막으로 my-pass 명령으로 패스워드를 확인해보자.