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

* 소스코드 분석



(darkknight.c)


소스코드를 보니 return 문장이 없고 바로 problem_child 라는 함수를 호출하고 있다.
그리고 그 안에서 argv[1]을 strncpy를 하면서 1바이트 오버플로우를 내고 있다.

fake ebp를 이용해 문제를 해결할 수 있다.
어떤 상황에 처해져있는지 메모리를 확인해보자!

늘 그랬듯이 44더미와 D 4개를 입력해준다. (실제로는 40바이트에 1바이트 오버플로우가 나지만 하던데로 입력해보았다.)



(gdb로 실행)



실행 후 problem_child 함수안에 들어가서 leave 명령어 전의 메모리 상황을 살펴보았다.


(leave 명령어 전)


빨간 박스쳐있는 곳이 이전의 ebp가 저장되어있는 자리이다. 그런데 지금은 한 바이트가 오버플로우 되어서 41이 입력되어있다. leave 명령어가 수행되면 ebp에 저 0xbffffa41이 입력될 것이다.




(leave 명령어 후)


leave 명령어 후 ebp를 살펴보면 0xbffffa41이 입력되있는 것을 확인해 볼 수 있다.
그렇다면 여기서 ret명령이 끝나면?
-> 그 다음 원래 main 함수의 leave + ret 문장을 수행하게 된다.

여기서 leave하게 되면 저장되어있던 ebp에 esp가 옮겨지고 
그 위치의 값을 ebp에 저장시킨다.

leave 하기 직전에 ebp를 살펴보면 0xbffffa41 인 것을 확인 할 수 있다.



(0xbffffa41로 옮겨간 ebp)


이렇게 되면 그 후 leave + ret 명령 수행 후 0xbffffa45에 있는 값이 eip 에 들어가게 된다.

이 것을 이용해서 문제를 해결할 것이다.
우리의 버퍼의 주소 앞으로 ebp를 잡게 해야하므로 주소를 확인한다.




(버퍼 시작 앞 주소)


0xbffffaa0 이다. 이 주소를 넣으려면 맨 마지막에 a0을 입력해주면 된다.

확인해보자!



(0xbffffaa0으로 fake ebp)


ebp 자리를 확인해보자.




(ebp 자리)


이 전 저장된 ebp 주소 자리가 0xbffffaa0 으로 바뀐 것을 확인할수 있다.

바로 이 주소로 ebp가 자리잡게 될것이다.



(ebp 상태)


여기서 main함수의 leave 명령어를 수행하면 그 다음 주소인 0xbffffaa4 주소의 값을 eip에 입력하려 할 것이다.



(ret 전 상황)


여기서 0x41414141 을 꺼내가려는 모습을 확인 할 수 있다.

이 것들을 토대로 다시 생각해본다.



(입력인자 구성)


입력 인자 첫부분에 실행시킬 주소(eip에 넘어갈 주소)를 넣는다. 지금은 D 4개의 값으로 대체한다.
그 후 마지막은 a0으로 입력해준다.

ret 명령 전의 esp를 확인해보면 D 4개를 꺼내가려는 것을 확인할 수 있었으므로 바로 이 자리에 0x41414141 에 nop과 쉘코드가 들어갈 것이므로 0xbffffaa8 을 입력하면 되는 것이다.



(마지막 체크 메모리 상황)



gdb로 최종 공격 전 확인 모습이다.



(최종 확인)


최종 확인 결과 nop이 실행되고 그 다음 쉘코드가 실행 되는 것을 확인 할 수 있었다.

이 토대로 공격을 수행하였다. :)
실제로에서는 메모리에서 0x00000010 바이트씩 차이가 날수 있으므로 왔다갔다 해주면서 위치를 잡으면 된다.



(공격 성공)



쉘을 획득하였다. :)

'WarGame > 500 Project' 카테고리의 다른 글

(30/500) Lord of the BOF - giant  (0) 2017.06.21
(29/500) Lord of the BOF - bugbear  (0) 2017.06.20
(27/500) Lord of the BOF - golem  (0) 2017.06.20
(26/500) Lord of the BOF - skeleton  (0) 2017.06.20
(25/500) Lord of the BOF - vampire  (0) 2017.06.20

+ Recent posts