Level19 풀이.
pw = 'swimming in pink'
일단 언제나 그랬듯이 문제 접근을 위해 hint를 본다.
뭔가 코드가 짧아졌다 일단 해석해보자면, char buf[20]은 문자형 buf 변수에 20byte의 크기를 할당한다는 뜻이고, gets(buf)는 gets 함수를 통해 buf변수에 사용자 입력을 받는다. printf(“%s\n”, buf); buf 내용을 출력한다.
일단 gets 로 인해 취약점이 생기는 것은 예제들을 통해 알 수 있고 근데 맨날 있던 setreuid( 숫자 어쩌구~~~~)가 안 보인다. setreuid를 알아내야 한다. 이럴 때 쓰는 방법이 chaining return to lib 기법 인데 구글링 참조했다.
일단 그러면 buf에서부터 ret 까지의 거리를 알아야 되고, system(), setreuid() 함수의 주소를 획득해야 한다. system 내부에 있는 /bin/bs 주소를 알아야 되고, setreuid 권한 정보를 알아야한다. chaining to lib 기법을 쓰기 위해 pop과 ret 명령어를 알아야 한다.
일단 lea eax[ebp-40] 는 buf에서 ebp까지의 거리를 나타낸다.
즉 거리는 40이고, buf에서 ret까지의 거리는 4byte 낮은 44일 것이다.
gdb로 디버깅을 시작하고, 브레이크 포인트를 시작 main 함수 시작부터 걸어준다. 프로그램 r 명령으로 시작하고, p 명령어를 통해 system 함수와 setreuid 함수의 주소를 알아낸다.
system 함수의 주소 = 0x4005f430 setreuid 함수의 주소 = 0x400f9cc0.
system 함수 내부에 /bin/bs 주소를 가져오는 코드다.
/bin/bs의 주소가 출력되는데, /bin/bs의 주소는 0x4014ad24.
그 다음은 SETREUID를 구해야 한다.
level20의 uid = 3100 3100은 0x0000C1C로 16진수로 변환후 사용.
즉 setreuid에 인자로 줄 때, 3100의 인자를 주면 된다. 그리고 chaining를 위한 pop과 ret 명령어 그룹을 가져온다.
setreuid를 사용하기 위해서 2개의 인자가 사용된다는 것을 확인한다. 그러므로 pop 2개와 ret 1개로 구성된 chaning 명령어 set가 필요하게 된다.
pop-pop-ret가 모든 연결되어 나오는 부분인 “8048849d” 확인 할 수 있다.
PPR의 주소 = 804849d.
즉 [buf – ret 까지의 거리] + setreuid 시작 주소 + PPR 주소 + ruid 값 + euid 값 + system 시작 주소 + 4byte 공간 + /bin/sh 주소.
최종 주소.
pw = 'we are just regular guys'
CF) 음................ 오히려 이전 문제가 더 어려웠던 거 같다.