#About


[그림 1] - giant.c 소스 코드 확인




#Solution


[ + ] 소스 코드 해석


1. buffer라는 char형 변수에 40바이트 할당 및 포인터 변수 선언


2. 조건문을 통해 사용자 입력 값이 2개 미만이면 argv error를 출력 후 종료


3. popen 함수와 각종 명령어 이용해 assassin이라는 프로그램을 사용함에 있어 필요한 공유 라이브러리 정보를 출력 후 포인터 변수 fp에 담음


[그림 2] - 사용된 명령어 해석


ldd는 List Dynamic Dependencies의 약자로 실행파일이나 공유 라이브러리들이 요구하는 공유 라이브러리를 출력하는 명령어 이며 위 [그림 2]에서 


확인할 수 있듯, grep libc를 통해 libc가 들어 있는 줄만 출력했고 이를 awk에 넘겨주어 4번째 필드 값인 (0x40018000)만 출력후 포인터 변수 fp에 담음


4. fgets 함수를 통해 buffer에 254 글자 만큼 fp에 담긴 값(0x40018000)을 담음


5. sscanf 함수를 이용해 포맷스트링 %x 형식으로 하여금 lib_addr에 buffer에 담긴 값을 씀


6. 3번 과정과 비슷하며 *.so 파일에 대한 심볼 정보를 확인하기 위해 nm 명령을 사용했으며 구체적인 사용법은 아래와 같다


[그림 3] - 사용된 명령어 해석


nm을 이용하여 __execve가 위치하는 offset 정보가 담긴 정보를 awk로 넘겨주어 첫 번째 필드(00091d48)의 값을 포인터 변수 fp에 담음


7. 3,6번 과정에서 구해준 lib_addr과 execve_offset를 더한 값을 execve_addr에 담음


8. memcpy 함수를 이용하여 사용자 입력 값 중 44번째부터 4바이트를 포인터 변수 ret에 담음


9. ret의 값과 execve_addr과 일치하지 않으면 You must use execve!를 출력 후 종료


10. buffer에 사용자 입력 값 argv[1]을 담고 출력.


전반적으로 해석이랍시고 휘갈겨 적은 감이 있긴하지만 간단히 한줄 요약하면 


execve함수와 RTL기법을 통해 문제해결을 유도하기 위한코드임


문제를 해결하기 위해서는 리턴 값이 execve 함수의 주소 값이여야하며 이를 RTL기법을 적용하기 위한 스택 구조는 아래와 같다


| \x90 (44byte) | execve (4byte) | system (4byte) | exit (4byte) | &"/bin/sh" |


위와 같은 스택 구조를 이루기 위한 system과 exit의 주소를 아래와 같이 gdb를 이용하여 구해 주었다


[그림 4] - 함수 위치 주소 확인


마지막으로 필요한 system 내의 문자열 /bin/sh가 위치하는 주소를 찾기 위해 아래와 같이 C 프로그램을 만든 뒤 컴파일 시켜주었다


[그림 5] - /bin/sh 주소 확인


Exploit을 함에 있어 필요한 함수의 주소 및 인자를 구했으므로 아래와 같이 페이로드를 작성할 수 있고 셸을 획득할 수 있다


[그림 6] - 셸 획득



+ Recent posts