#About


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




#Solution


[ + ] 소스 코드 해석


1. buffer라는 char 형 변수에 40바이트를 할당


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


3. 조건문을 통해 사용자 입력 값 중 48번째 바이트가 \xbf면 stack retbayed you!를 출력 후 종료


4. 조건문을 통해 사용자 입력 값 중 48번째 바이트가 \x40면 library retbayed you, too!!를 출력 후 종료


5. 사용자 입력 값을 buffer에 복사한 뒤 buffer 값 출력


6. memset 함수를 통해 buffer와 sfp 값 초기화


이번 문제는 리턴 주소가 라이브러리 영역을 의미하는 \x40으로 시작하거나 스택영역을 의미하는 \xbf를 사용할 수 없다.

이러할 경우에는 RET SLED라는 기법을 이용해서 이용할 수 있으며 그 원리는 다음과 같다


함수를 종료하는 과정에서의 ret은 pop eip > jmp eip 와 같이 동작을한다. 이 때 pop 명령을 진행하므로 esp 값은 +4바이트 증가한다 

따라서 이 때 ret에 한번 더 ret의 주소를 넣어주게 되면 원래 ret 값의 4바이트 뒤 부분을 사용할 수 있으며 이를 이용한 페이로드 구상도는 아래와 같다


| 0x90 (44byte) | ret (4byte) | &argv[2] (4byte) | \x90 (100) | 셸 코드 (48byte) | 


환경변수도 이용할 수 있지만 argv[2]를 이용하여 문제를 해결할 것이며, 먼저 gdb를 이용하여 ret 주소를 찾을 수 있었다


[그림 2] - ret 명령이 담긴 주소 확인


또한 argv[2]를 이용할 것이므로 argv[2]의 시작주소를 찾아야 하므로 아래와 같이 진행해주었다


[그림 3] - 중단점 설정 및 임의의 페이로드 입력


AAAA부분은 ret 명령이 담긴 주소 값이 될 것이며 BBBB부분은 argv[2] 즉, D가 시작하는 곳이라고 생각하면 된다


위와 같이 입력해준 페이로드가 담긴 메모리를 살펴 보았더니 아래와 같이 값이 담긴것을 확인할 수 있다


[그림 4] - 메모리에 담긴 값 확인


빨간 부분은 ret 명령이 다시 담기게 될 부분이며, 파란 부분은 argv[2]의 시작주소가 담길 부분, 초록 부분은 셸 코드가 담길 argv[2]의 시작 부분이다

(0xbffffbe3)


따라서 페이로드는 아래와 같아 진다


| 0x90 (44byte) | 0x0804851e | 0xbffffbe3 | 셸 코드 |


[그림 5] - giant 권한의 셸 획득


/home/giant/tmp/assassin이 아닌 /home/giant/assassin에 위 과정을 똑같이 해주면 아래와 같이 assassin 권한의 셸을 획득 할 수 있다.


다만 경로가 바뀌므로 입력된 페이로드의 메모리상의 위치가 조금 달라질 수 있음을 유념하자


[그림 6] - 셸 획득



+ Recent posts