BOF 원정대의 giant를 잡아보자!

* 소스코드


(giant.c)


중간에 복잡해보이는 코드가 있는데 친절하게 주석으로 설명이 되어있다.
ret주소에 execve 함수 주소가 들어가있는지 체크하기 위한 부분이다. 그렇기에 ret 주소에 execve를 넣어 execve 함수를 사용해서 문제를 해결하라는 의도같다.

그렇다면 execve를 어떻게 써야하나 구성인자를 살펴보자!



(execve 함수)



execve 함수의 인자
1. 파일이름(실행할파일)
2. 인자 주소(파일이름 문자열의 주소)
3. Null 문자열

예를 들기위해 C언어로 표현하여 실행해 보겠다



(execve c 코드)



(실행화면)



위와 같이 인자를 넘겨주니 execve 함수가 잘 실행되었다.

자 이제 이대로 인자를 만들어주어야한다.



(ret 주소)



ret 주소는 0x400a9d48 (execve 함수 주소) 를 넣었다.
이제 이 뒤에는 더미(4바이트) 를 넣은 후 그 뒤부터 인자가 들어가게된다.

execve 함수로 실행할 파일은 /bin/sh이다. 이 문자열을 직접 써주어도 되지만 그렇게 되면 문자열 주소를 넘겨주는 두번째 인자를 구성할 때 어려워진다. 왜냐하면 두번째 인자는 포인터 배열이기 때문에 주소와 널문자(4바이트)로 이루어져야하기 때문이다.

그렇기에 이미 로딩된 라이브러리에서 /bin/sh 문자열을 찾아 사용할 것이다.
system 함수 근처에 /bin/sh 문자열이 존재한다는 것을 알고 있기에 간단히 c코드를 만들어 /bin/sh 문자열 위치를 찾아낼 것이다.




(/bin/sh 주소찾기)



(/bin/sh 주소)



직접 gdb를 열어 해당 주소를 검색해보자.



(/bin/sh)



해당 주소에 /bin/sh 문자열이 들어있는 것을 확인 했다.

이제 첫번째 인자로 우리가 찾은 주소를 넣을 것이다.
두번째 인자를 구성해야한다. 일단 지금까지 만든 것을 토대로 메모리를 확인해보자.

A*44 + execve함수주소 + A*4(더미) + "/bin/sh주소" + "/bin/sh주소가 적힌 포인터배열 주소" + NULL

포인터배열을 만들계획이다. 일단 포인터배열 주소를 C*4 로 대체하고 메모리를 확인해보자!



(gdb 실행)


두번째 인자를 만들어줄 위치를 살펴보니 적당한 위치가 나왔다.



(4바이트 NULL)


포인터배열이기 때문에 주소뒤에 Null(4바이트)가 나와야하는데 우리가 입력은 못한다. 그렇기에 이미 존재하는걸 이용해야하는데 0xbffffae8 에 널 4바이트가 있다. 그러므로 그 앞에 문자열 주소를 입력한 후 해당 위치를 두번째 인자로 넘겨줄 것이다.

세번째 인자 Null은 0xbffffae8을 넘겨줄 것이다. 해당 주소가 이미 Null이기 때문에



(포인터배열)



위와 같이 포인터 주소배열을 만들 수 있다.



(포인터 배열)


0xbffffad4 위치에 정확히 포인터 배열이 들어갔다.
이제 두번째 인자로는 0xbffffad4를 
세번째 인자로는 0xbffffad8을 넣어줄 것이다.

마지막으로 확인 해보자.



(최종 확인)



해당 인자에 알맞은 값이 들어갔는지 체크!

공격!
0x10 바이트 앞뒤로 왔다갔다 하면서 올바른 위치를 잡았다.



(공격 성공)



쉘 획득!


+ Recent posts