FTZ_level18

해킹/FTZ 11~20 2016. 1. 13. 22:01

level18의 hint 내용.

음.... 소스코드가 계속 비슷하다고 불평했더니 달라도 너무 다른놈이 나왔다.

문제의 목적은 check변수에 0xdeadbeef라는 값을 넣는 것이다.

솔직히 옛날에 이문제를 어떻게 풀었을까라는 생각도 했다. 모르는 함수가 너무 많다. 사실 중요한 부분은 아니니 대충 넘기고 풀었겠지만..

어쨋든 대충 공부한 바로는


-fd_set이라는 자료형은 fd들의 활성화 여부(맞나?)를 나타내는 테이블로 구성되는데... 즉 stdin에 내용이 없으면 fd[0]=0 있으면 fd[1]=1 이런식으로 사용되는 것 같다.


-FD_ZERO 함수는 이 테이블들을 전부 0으로 세팅해주는 함수인 듯 하고.

-FD_SET부분의 내용은 stdin을 1로 바꾼다는 뜻인것 같다.

즉 모든 fd들을 비활성화 하고 stdin만 켜놓은 상태를 만드는 것 같다.


-그리고 select 함수는 활성화된 fd의 갯수를 반환하므로 select함수가 들어간 if문은 입력값이 있는가를 판한하는 내용으로 보인다.

-FD_ISSET 역시 select와 비슷하게 stdin이 세트되어 있는지를 확인하는 것 같은데 왜 두개를 중복해서 사용했는지는 의문이다.


뭐 그래서 결론을 말하자면 fd=0 즉, stdin만 빼고 모든 fd를 강제로 비활성화 시킨 뒤에 stdin으로부터 한글자씩 read해서 string[count]에 집어넣겠다는 뜻으로 보인다.

왜 저렇게 쓸데없이 복잡한 함수들을 사용했는지는 모르겠다. 뭔가 이유가 있을텐데 궁금하지는 않다.

일단 디버깅을 해보자.

이번 레벨의 디스어셈 코드는 너무 길어서 필요한 일부만 가져오도록 하겠다.




먼저 눈에 들어오는건 main+12, +19 부분이다.

ebp-108, ebp-112에 각각 0을 집어넣어줬다.

c 코드 상에서 int x=0; int count=0;에  해당하는 부분이다. ebp-112가 count변수라는 정보를 알수 있다.






두번째로 main+91에 0xdeadbeef와 비교하는 부분이 나온다. ebp-104부분이 check변수에 해당하는 부분이라는 것을 말해준다.




그다음은 cmp와 je가 여러번 반복되는 것으로 보아 switch case 부분이다.

이부분 자체가 많은 정보를 가지지는 않지먄 이부분의 jmp, je 주소를 보면 흐름을 파악하기 쉽다.

여기에서 jmp main+499라는 부분이 나오는데 이부분이 default의 경우에 실행하는 문장이다. string[100]배열에 대한 단서가 필요하므로 따라가보자.





이 default 부분이 많은 단서를 포함하고 있다. 상당히 복잡한 어셈블리 코드지만 인내심을 가지고 살펴보자.

먼저 ebp-100의 주소가 어떻게 이동하는지 살펴보자


main+499에서 ebp-100이 eax로 들어가서 그다음 문장에서 ebp-252로 들어간 다음 최종적으로 main+526에서 ecx 레지스터로 값이 들어간다. 보기쉽게 정리하면

ebp-100 -> eax -> [ebp-252] -> ecx 이렇게 된다. (그냥 ebp-100 은 실제 ebp에 들어있는 주소에 -100을 한 값을 뜻하고 []에 묶인 [ebp-252]는 ebp-252가 가르키는 주소에 들어있는 값을 뜻한다 오해가 없길 바란다.)


한편으로 아까 count인것을 확인한 ebp-112 부분은 edx로 들어간다.

리고 main+532에서 al에 든 값을 [edx+ecx]로 옮기는데 이부분이 바로 string[count]=x; 부분이다.


즉 ebp-100이 string이라는 배열의 시작주소이고 이 시작주소에 count만큼 더한 부분에 stdin에서 한글자를 가져와 집어넣는다는 내용이다.

포스팅의 맨 앞에서 언급했듯이 목적은 check변수에 0xdeadbeef라는 값을 넣는 것이고 디버깅하며 살펴본 바로는 이 변수는 ebp-104에 위치한다.(main+91 참고)


그렇다면 ebp-100인 string의 주소에서 -4반큼 더한 ebp-104에 값을 넣어야 하므로 count를 -4로 만들면 되겠다.

편리하게도 c 코드를 보면 switch case 문에서 0x08일 경우 count--를 하게 되어있다.

즉 0x08을 네번 입력해서 count를 -4로 만들어준 뒤 0xdeadbeef를 입력해주면 될 것이다.


페이로드는 (python -c 'print "\x08"*4+"\xef\xbe\xad\xde"';cat)|./attackme

실행해보면




쉘이 잘 떴는지 my-pass로 확인해 보니 성공했다.

끝-



ps.이 프로그램에 입력을 몇개 넣어보다 보면 switch case문에 나와있는 문자열을 입력하면 printf 함수가 실행되서 뭔가 출력을 뱉어야 하는데도 프로그램이 출력을 뱉지 않는것을 알 수 있다. 아마도 FD_ZERO에서 stdout을 비활성화 했기 때문이 아닌가 싶다.

'해킹 > FTZ 11~20' 카테고리의 다른 글

FTZ_level20  (0) 2016.01.14
FTZ_level19  (0) 2016.01.13
FTZ_level17  (0) 2016.01.13
FTZ_level16  (0) 2016.01.13
FTZ_level15  (0) 2016.01.13
Tags
Social