#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] - 셸 획득
'Wargame' 카테고리의 다른 글
[Lord of Buffer Overflow] Zombie_assassin > Succubus (0) | 2017.11.30 |
---|---|
[Lord of Buffer Overflow] Assassin > Zombie_Assassin (0) | 2017.11.27 |
[Lord of Buffer Overflow] Bugbear > Giant (0) | 2017.11.25 |
[Lord of Buffer Overflow] Darkknighht > Bugbear (0) | 2017.11.21 |
[Lord of Buffer Overflow] Golem > Darkknight (0) | 2017.11.21 |