HanJeouk의 개인공부 블로그

2017 Codegate Final petshop

CTF2018. 3. 27. 01:49

C++ 포너블을 공부하려고 푼 문제다.

Buy 함수를 보면

이렇게 되어 있다. #밑부분도 위에 윗부분과 같기 때문에 생략

Dog_go_input_Data_to_heap_ptr로 가면

또 input_Data_to_heap_ptr이라는 함수가 있다. 또 들어가서 보면

이전에 할당된 청크에 데이터를 넣어준다.

그리고 이렇게 청크를 Dog라는 청크를 할당하고 gdb로 heap 상황을 봤을 때

요로코롬 돼 있다. #gdb로 동적 분석하는 게 훨씬 분석이 쉽고 빠르더라

위에 0x21만큼 할당됐는데 이건 캡쳐는 안했지만 프로그램 시작할 때 할당을 하더라.

그리고 데이터 영역 16바이트에 할당한 청크의 주소를 가리킨다. 16바이트니까 2개까지 animal 추가가 가능하다.

0x616c30 에는 animal 추가한 개수다. 추가할 때마다 1씩 올라간다. 첫 번째 사진을 보면 if 문으로 -1인지 아닌지 확인하는게 보일텐데 간단히 그냥 2개 이상 할당 못하게 하려고 하는 것이다. 0x51의 사이즈를 가진 청크는 추가한 animal 청크다. 0x4027a0은 그냥 할당할 때 추가해주더라

그 뒤에는 아까 넣은 문자열들이다.("Dog", "Bark", "Dog Food") 문자열 다음에는 포인터가 보이는데 저건 나중에 공격 때 쓰이는 name의 포인터다. 저걸 가지고 릭이든 공격이든 전부 다 할 수 있다.

다음으로 Sell 함수를 보면

C++이라 더럽게 생겼지만 그냥 할당했던 청크들 for문 돌려서 free 시키는 것이다.

이제 set_pet을 보자.

input_new_name, input_sound, input_new_feed 가 보인다. 이 함수에서 취약점이 발생한다.

이렇게 제한없이 값을 입력받을 수 있기 때문이다.(name, sound, feed 다 똑같다.)

아까 gdb 모습을 봤듯이 이렇게 값을 원하는 만큼 넣는게 가능해진다면 포인터 조작이 가능하다는 걸 생각할 수 있다.

다음은 list_pet 함수다.

for문으로 청크들의 name, sound, feed, person의 값들을 다 출력해버린다. 그래서 person 포인터를 set함수에서 조작하고 list_pet 함수에서 조작한 person 포인터를 출력시킨다면 우리가 원하는 값을 출력시킬 수 있다.

마지막으로 set_name 함수다.

청크에 있는 person 포인터에 값을 쓴다. 즉, person 포인터를 조작한다면 조작한 주소에 값을 넣을 수 있다는 말이다.

이제 이 함수들을 가지고 릭과 공격을 하면된다.

우선 릭을 하기위해 set함수로 person_name 포인터를 함수의 got 덮고 list 함수로 원하는 함수의 주소를 얻어 그걸로 system등 공격에 필요한 함수의 주소들을 얻었다.

이제 공격을 하면 된다. 공격도 set 함수를 이용했다. person_name의 포인터를 free_hook으로 덮고 setname으로

free_hook에 system 주소를 넣었다. 이제 free를 호출하면 free대신 system이 실행 될 것이다.

sell 함수가 free를 할 때 person_name 포인터도 free 시키길래 또 set으로 person_name 포인터를 /bin/sh로 덮어서 system("/bin/sh")가 실행되게 했다.

문제를 최대한 빨리 푼다는 생각으로 풀어서 약간 풀이가 미흡할 수도 있다 ㅎ...






'CTF' 카테고리의 다른 글

2018 Codegate Final heapbabe & 후기  (0) 2018.04.08
2017 Codegate Final building_owner  (0) 2018.03.29
2016 Hitcon sleepy holder [Again]  (0) 2018.03.22
2016 Hitcon secret holder [Again]  (0) 2018.03.21
2017 hitcon training zoo  (0) 2018.03.14