함수의 프롤로그와 에필로그에 관한 고찰 + fake ebp(실패)

해킹/개념 정리 2016. 1. 13. 00:17




이 실험의 기본적인 목적은 함수의 플롤로그와 에필로그에서 어떠한 일이 일어나는지 관찰하는것.

그것을 용이하게 하기 위해 굳이 간단한 출력을 func()라는 함수까지 만들어서 하고 있는 것이다.

그리고 그 에필로그와 프롤로그를 잘 관찰한 뒤에 facke ebp를 사용해서 SFP까지만 덮어서도 프로그램의 흐름을 바꿀 수 있는지 시도해보려고 한다.



먼저 그림과 같이 func를 call 하는 라인에 브레이크포인트를 걸었다. 해당 부분까지 실행해보면...



이부분에서는 레지스터만 보고 넘어간다.

esp:0xbffff780

ebp:0xbffff788

을 각각 가르키고 있다. stepi를 해서 func 안으로 들어가서 다시 레지스터를 확인해 보자





esp:0xbffff77c

ebp:0xbffff788

ebp는 그대로인데 esp가 -4만큼 늘어났다. esp에 뭔가 push 되어있다는 뜻이다. 해당 부분을 확인해봤다.





esp가 가르키고있는 0xbffff77c 메모리 주소에는 0x0804854a가 들어있었다. 이 주소는 main+11,

call func를 하는 main+6의 바로 다음주소, 즉 리턴주소가 들어간 것이다.

call 명령어가 실행되면 단순히 그자리로 점프하는 것이 아니라 현재 esp가 가르키고 있는 자리에 돌아올 주소를 push하고 점프하는 것이다.


이제 func에서 실행될 명령어는 함수의 프롤로그인 push ebp; mov ebp, esp 명령어들이다.

사실 자명하긴 하지만 그래도 과정을 확실히 이해하기 위해 하나씩 돌려봤다.




esp:0xbffff778

ebp:0xbffff788

보다시피 esp가 추가로 4만큼 빠지면서 그 자리에 0xbffff788이 들어갔다. ebp에 들어있던 값이다.

이부분이 바로 다시 main함수로 return 할때 ebp에 저장될 SFP라는 값이다. leave라는 과정에서 SFP가 ebp롤 pop 되어서 올라간다.

이제 mov ebp, esp 부분이 실행될텐데 당연히 ebp가 현재 esp의 위치까지 당겨질 것이다.

마찬가지로 과정을 이해하기 위해서 인내심을 가지고 돌려보자.




esp:0xbffff778

ebp:0xbffff778

예상과 같이 ebp를 당겨왔다. 파란글씨로 esp와 ebp를 쓰는 이유가 나중에 두 레지스터를 기준으로 그림을 그려보기 위해서다.

이제 프롤로그를 다 봤으니 에필로그인 leave ret 부분까지 넘어가보자.





leave앞에서의 레지스터 상황이다. 

함수의 에필로그는 leave || ret 두가지로 이루어진다.

leave는 mov esp, ebp; pop ebp 두가지를 하나의 명령어로 묶은 것이고.

ret은 pop eip; jmp eip 두가지 명령어를 하나로 묶은 것이다.

내가 이해하기로는 프롤로그인 call ~~~; push ebp; mov ebp, esp 의 완벽한 역과정인것 같다. 확실히 대칭을 이룬다.

이제 leave를 하면 ebp 뒤에 있는 0xbffff788이 ebp로 들어갈 것이다. 




예상대로 스텍에서 SFP 부분에 있던 값이 ebp레지스터에 들어갔다.

이제 ret을 하게 되면 ebp+4부분에 있는 0x0804854a로 가게 될 것이다. 큰 의미는 없지만 실행시켜보면.




메인으로 돌아온 것을 확인했다.


좀 길어지고 뭘하려는건지 모르게된 감이 있는데... 이렇게 함수 func의 프롤로그와 에필로그의 과정을 알아봤다.

사실 SFP가 어떻게 작동하는지 눈으로 보기 위해서 해본 실험이었다.

결론은 SFP는 ret명령이 실행되면서 이전에 실행되던 함수로 돌아가려고 할 때 ebp를 저장해놓는 백업용도로 사용하는 것 같다.



그리고.... 이게 포스팅을 하게되면서 알게 된 사실인데 부끄럽지만 저 프로그램을 일부러 취약하게 만들었는데  우분투에서 컴파일하니 취약점이 사라져버렸다.

코드를 보면 SFP부분을 덮을수 있게 4바이트 영역에 8바이트 입력을 받는데 컴파일러가 스텍을 12바이트나 늘려버려서 SFP를 덮을수가 없었다.

취약한 바이너리를 가져와서 다시 시도해 보겠다.

.....


......


한참을 시도했으나 취약하게 만드는데 실패했다-_-;; 정확히는 fgets하는 과정에서 끝에 한바이트가 null로 바뀌면서 리턴을 한바이트 덮어버려... 세그폴트가 나며 꺼져버린다.. 허허 어쩔수 없이 fake ebp는 다음에 하는걸로




'해킹 > 개념 정리' 카테고리의 다른 글

쉘코드 작성법  (0) 2016.01.16
ASLR의 개념  (0) 2016.01.13
다중 파이프 페이로드  (0) 2015.11.24
GOT overwrite  (0) 2015.11.24
UPX  (0) 2015.11.24
Tags
Social