서브웨이

pwnable.kr passcode 풀이 본문

Pwnable/pwnable.kr

pwnable.kr passcode 풀이

샌드위치메이커 2020. 7. 21. 22:37

너무 오랜만이네요. 이번 학기는 코로나라는 재앙때문에 아주아주 힘든 바쁜 학기였습니다.

오래간만에 문제를 풀어봅시다.

자 오랜만이라 새롭네요. 대충 읽어보자면 어머님꼐서 패스워드를 사용하는 로그인 시스템을 만들라고해서 C로 만들었는데 에러는 없지만 컴파일 할 때 경고가 뜬다. 뭐 이런 내용이네요.

이런 파일들이 있네요. 일단 코드를 봅시다.

자 그럼 컴파일 경고가 뜬 부분을 찾아봅시다.

login 함수에서 scanf를 쓸 때 인자에 &를 안써줬네요(welcome에선 어차피 배열이니 안써도 된다는건 다 아실거라 믿습니다). 저렇게 되면 passcode1, passcode2에 있는 쓰레기 값이 가리키는 주소에 입력한 값을 넣게 됩니다. 이상한 주소에 접근하려하니 당연히 segmentation fault가 뜨겠죠?

역시나입니다. 그럼 실수한 부분을 찾았으니 이제 어셈코드를 보며 어떻게 접근을 해야할지 구상해봅시다.

간단히 생각해보면 우리가 할 수 있는 부분은 입력밖에 없으니 세개의 scanf문으로 무언가를 해야할 것으로 예상됩니다.

먼저 메인을 봅시다. 별거없네요. 그냥 실행후 메시지 띄우고 welcome, login, 메시지 순으로 동작합니다.

참고로 서버상에서 peda는 gdb를 키고 source /usr/share/peda/peda.py를 입력하면 사용할 수 있습니다.

welcome의 어셈코드는 다음과 같습니다. +3에서 name을 위해 스택에 공간을 확보하는 모습을 볼 수 있습니다. 더미까지 포함해서 136바이를 확보하고 있네요.

name이 위치한 곳은 +48에서 scanf가 호출되고 있으니 그 위에서 전달할 인자를 스택에 저장하는 부분을 보면 됩니다. +38에서 ebp-0x70의 주소를 edx에 넣고, 그 다음줄에서 esp+0x4에 복사하는 것으로 보아 name인 것 같습니다. esp에는 %100s가 들어갈 것 같네요. 확인해봅시다.

guessed arguments를 보면 예상이 맞다는 것을 알 수 있습니다. 그럼 0x70에서부터 0xC까지 name이 위치하고 있다는 것을 알 수 있습니다. 더 이상 할건 없어보이니 login으로 넘어갑시다.

자 대충보면 프린트해주고 입력해주고를 반복하고 비교해서 분기해주는 것을 알 수 있습니다. +34 부분이 passcode1을 입력하는 곳이겠죠?

맞네요. 그럼 login의 +19부터 scanf함수에 쓸 인자들을 하나씩 스택에 저장하는 것을 볼 수 있습니다.

그런데 +24를 보면 ebp-0x10 부분에 있는 값을 edx로 저장하여 +27에서 스택에 저장하는 것을 볼 수 있습니다. 아까 코드의 scanf에서 &을 빼먹었기 때문에 변수의 주소값이 아니라 변수의 값 자체를 주소로써 스택에 저장하게 됩니다. 만약 정상적으로 &을 붙였다면 lea edx, [ebp-0x10]이 됐겠죠?

여기서 생각해보면 아까 welcome에서는 ebp-0x70에서부터 ebp-0xc에 name이 위치하고 login에서는 ebp-0x10부터 ebp-0xc에 passcode1이 위치하므로 passcode1과 name의 끝 4바이트가 같은 위치에 있다는 것을 알 수 있습니다. 그런데 welcome이 실행된 후 사이에 다른 동작이 없이 바로 login이 호출되므로 name에 입력한 값이 그대로 스택에 남아있을 것입니다. 일단 확인해봅시다.

name으로 A를 100개 입력해주고 브레이크포인트를 걸어보면 passcode1에 해당하는 값이 ebp-0x10에 위치하고있고 ebp가 0xfffc9a48이므로 passcode1은 0xfffc9a38임을 알 수 있습니다. 그런데 스택을 보면 해당위치에 name으로 입력한 A 100개의 마지막 4바이트인 AAAA가 저장되어 있습니다. 이렇게 되면 name의 마지막 4바이트가 가리키는 값을 주소로 하는 곳의 값을 수정이 가능하게 됩니다.

그럼 이제 어떤 값을 수정해야 할까요?  일단 passcode1은 원하는 값으로 수정이 가능하지만 어차피 segmentation fault가 발생하기 때문에 정상적인 코드 진행은 불가능해보입니다. 그럼 유일한 방법은 실제로 유효한 주소에 해당하는 값을 변경해주는 방법밖에 없습니다.

자 여기서 plt와 got라는 개념이 등장합니다. 간단하게 설명하면 외부 라이브러리에서 처음 함수를 불러올때 plt라는 곳에 저저장된 got의 주소를 통해 got라는 곳으로 점프하게 되는데 got에는 라이브러리에서 사용할 실제 함수의 주소가 들어있어 그곳에서 함수를 가져오게 됩니다.(제가 이해한것에 오류가 있다면 댓글로 알려주시면 감사하겠습니다...)

자세한것은 https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/

 

PLT와 GOT 자세히 알기 1

Dynamic Linking 과정을 추적해 PLT와 GOT를 이해해보자 :) 시스템 해킹을 공부하시는 분들이라면 PLT와 GOT에 대해 알고 있을 것입니다. 이제 막 시스템 해킹 공부를 시작한 분들도 한 번 쯤 들어보셨을

bpsecblog.wordpress.com

이곳을 참고해주십쇼...

그럼 외부 라이브러리에서 불러오는 함수를 사용할때 got에 있는 주소를 수정하여 원하는 주소로 점프할 수 있게 됩니다. 그럼 문제 코드의 login의 +34이후에 외부 라이브러리를 사용하는 함수를 찾아봅시다.

다시 한번 login의 어셈코드를 보면 fflush와 puts를 외부에서 불러오는 것을 볼 수 있습니다. 그럼 fflush를 노려봅시다. 일단 fflush의 plt에 해당하는 곳을 봅시다.

0x804a004에 해당하는 got로 점프하는 것을 볼 수 있습니다. 그럼 해당 부분을 조작하여 system("/bin/cat flag");를 호출하기 시작하는 login의 +127로 바꿔주면 흐름이 바로 그곳으로 넘어가게 됩니다.

그럼 파이썬을 사용해 페이로드를 작성하고 실행시켜봅시다. 페이로드는 A*96 + 0x0804a004(got의 주소) + 134514147(login+127의 주소 0x080485e3를 정수로 변환)로 구성됩니다. 참고로 passcode1을 입력받을때 정수로 입력받으므로 login+127의 주소를 정수로 변환해주어야합니다.

짜잔

'Pwnable > pwnable.kr' 카테고리의 다른 글

pwnable.kr input 풀이  (0) 2020.08.11
pwnable.kr random 풀이  (0) 2020.08.11
pwnable.kr flag 풀이  (0) 2020.02.18
pwnable.kr bof 풀이  (0) 2020.02.04
pwnable.kr collision 풀이  (0) 2020.01.29
Comments