pwnable.kr - passcode

Mommy told me to make a passcode based login system.
My initial C code was compiled without any error!
Well, there was some compiler warning, but who cares about that?

ssh passcode@pwnable.kr -p2222 (pw:guest)
컴파일러 경고가 났는데 그걸 무시했다고 한다. 미친놈인가? 컴퓨터님이 하시는 모든 말씀에는 다 뜻이 있다고 하는 옛말을 무시한 대가를 이 프로그래머 녀석은 톡톡히 치를것이다. 하여간,,,요즘,,,코딩공부하는,,,학생들이란,,,
이거 봐라. 작동이 안된다. 역시 컴퓨터님은 틀린 말씀을 하지 않으신다.
우리의 목적은 플래그를 따내는것이니 이것을 활용하면 될거같다.
소스코드를 한번 봐볼까?

오호. scanf로 integer 형의 자료를 입력받는데 &를 적어주지 않았다.
그 말인즉, scanf함수가 인자로 받은 값(passcode1과 passcode2에 들어있는 초기화 되지 않은 값)을 주소로 생각하고 그곳에가서 값을 쓰려했더니 접근할 수 없는곳이어서 segment fault가 떴다고 추측 할 수 있겠다.
아무튼 우리의 목표는 passcode1에는 338150을, passcode2에는 13371337을 넣어주는것이다.

반면 해당 소스코드의 밑 부분에는 100사이즈 짜리 캐릭터형 배열 name을 입력 받는 welcome() 함수가 선언되어있는데, 위에서도 정상 작동되었고, 코드상의 특이점도 없었다.
즉, 우리가 수정 가능한 공간은 name이라는것이다.

이 부분을 어셈블리로 한번 살펴보자.


esp에 0x88만큼의 사이즈를 할당해주는것을 알 수 있다. 이는 10진수로 136이므로 100만큼을 할당하고 더미로 36정도가 있다는것을 알 수 있다.

또, +33부터 +45까지 보도록하자, ebp-70의 주소를 edx에 넣고
이 값을 esp+04의 위치에 넣고, +45에서는 esp에 0x80487dd 를 넣는것을 보아 ebp-70이 name의 시작주소라는것을 알 수 있따!(인자를 넣을때 어셈블리에서는 스택의 LIFO구조 덕택에 C코드에서의 인자 순서와 반대로 들어가게 된다)

이제 로그인을 보도록하자.
캡션 추가
+24에서 보면 알 수 있듯 같은 이유로 passcode1도 ebp-10에 있다.
integer의 크기는 4바이트이니 passcode1에게 할당된 공간은 ebp-10부터 ebp-c일 터.
ebp-70의 사이즈도 ebp-c까지이다. 그러니까 name의 끝 4바이트는 passcode1이라는것이다. 덮어씌우기가 가능하니 공격도 가능하다.(플래그 따내기가 가능하다!)

"아니 슨상님?? passcode2는 못건들이는데요..?"

맞다. 그래도 공격 할 수 있다. system 함수가 그냥 바로 실행되도록 하면 된다.(흐름을 바꿔준다는 소리이다)
그런데 그 뒤에있는 함수 fflush는 버퍼를 지워버리기 때문에 그냥 바로는 못하고,
fflush의 got를 구해서 fflush의 호출 부분에 해당하는 주소에 system함수의 위치를 덮어씌우면 된다.
위에 있는 fflush@plt의 주소를 조회하면, plt가 가르키고있는 got의 주소를 알 수 있을것이다. 슥삭.
0x804a004. 요놈이 got이다.

그렇다면 system함수가 호출되는 곳은 어딨을까? 또 찾아보자. 아까 위에서 말한곳의 +127을 보아라.

ㅎㅇ.

그렇다면 페이로드는 다음과 같을것이다.
96개의 아무 값 + fflush의 got주소 + system 함수가 호출되는곳의 주소(%d로 입력받으니까 10진수로 바꿔야함)

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

햇갈릴게 따로있지.. 경고 무시하고 코딩하는 놈은 아주아주 혼나야한다. 부모님께 코딩을 배운다면 더더욱 죄송하도록.


컨셉 죄송합니다. 그래도 컨셉질 하면서 푸니까 재밌네요.

Comments

Popular Posts