본문 바로가기

High Level Technique/System Hacking

Buffer Over Flow (BOF)

Buffer Over Flow (BOF)




개념


Buffer Over Flow (이하 BOF, bof)는 정해진 공간에 정해진 만큼 값을 넣어야 하지만 "크기 제한"을 하지 않아 정해진 공간 보다 더 값을 넣을 수 있는 취약점을 말합니다.


가령, buf[10]이라는 배열을 만들었다면 buf라는 배열은 총 10개의 공간을 갖게 됩니다. 하지만, 프로그램이 실행 되면서 buf에 10개의 값이 아닌 11개, 12개 혹은 그 이상의 값이 들어가는 것을 확인하지 않고 처리함 으로서 발생하게되는 취약점을 뜻합니다.


bof는 stack에서 발생하기 때문에 stack corruption 으로도 불립니다.













설명





위 소스코드를 보면 매우 간단한 프로그램입니다. buf라는 char형 배열은 총 8개의 공간을 갖고 있고, scanf를 이용해서 buf에 값을 입력 받습니다.


입력을 받는데 "크기 제한"을 두지 않았기 때문에 scanf에서 취약점이 나타날 수 있습니다.


이제 위 소스코드로 작성된 프로그램을 분석해 보도록 하겠습니다.




<먼저 공부하시길 바랍니다.!!>


GDB 사용법: http://kblab.tistory.com/119

스택 구조: http://kblab.tistory.com/120     http://kblab.tistory.com/59

프롤로그, 에필로그: http://kblab.tistory.com/121















프롤로그와 에필로그에 대해서 공부를 하셨다면 첫 두 줄이 프롤로그, 마지막 두 줄이 에필로그 라는 것을 알 수 있습니다.

3번째 줄을 보면 sub esp, 0x10 인 것을 볼 수 있는데, 이것은 해당 프로그램이 스택을 사용하기 위해서 공간을 확보하는 것입니다.




위 그림을 보면 이해를 할 수 있을 것입니다.






스택 구조에 대해서 추가적인 설명을 하자면 위 어셈블리 코드를 보면 scanf가 실행되기 전에 esp와 esp+0x4에 값을 넣고 있는 것을 알 수 있습니다.

esp는 ebp와 함께 스택에서 사용되는 레지스터인데, 왜 값을 넣고 있는 것 일까요?



scanf()를 사용할 때 넣은 인자 값이 2가지가 있었습니다.

하나는 "%s" 나머지 하나는 buf 였습니다.


바로 이 2가지의 인자를 이용해야 하기 때문에 값을 넣고 스택에 쌓아두게 되는 거죠.

각 값을 확인 해 보도록  하겠습니다.





esp의 위치부터 2개의 값을 가져왔습니다.


하나는 0x80484f0이고, 다른 하나는 0xbffff150입니다.


scanf가 필요한 인자 값이 2개 였으므로 각각 %s와 buf를 나타내게 되는거죠.



scanf를 실행 후 buf의 주소를 확인해 보면 값이 쌓여있는 것을 알 수 있습니다.





1234라는 값을 입력했더니 0x34333231이라는 값이 저장되었습니다.


1234라는 값이 각각 hex값으로 들어가게 된 것입니다. 하지만 값이 4321로 들어갔습니다. 


리틀엔디안, 빅엔디안: http://kblab.tistory.com/58


리틀엔디안과 빅엔디안 차이에 따라서 값이 들어가는 방향이 결정됩니다.












자 이제 값이 어떻게 들어가는 지 확인 해 봤습니다. scanf가 취약점이 발생한다고 했으니 어떻게 되는지 알아보도록 하겠습니다.





이번에는 12345678을 입력했습니다. 위 스택처럼 값이 쌓이는 것을 알 수 있죠.

애초에 buf의 공간이 8이였는데 8자리를 모두 사용했습니다. 


크기를 제한하지 않으므로 값을 더 입력해 보겠습니다.





값을 더 입력했더니 뒤에 존재했던 값들이 모두 덮어씌워져 버렸습니다.


이 상태에서 프로그램을 진행시키면 다음과 같이 나타납니다.




0x36353433 의 위치로 이동하게 된 것입니다. 저 값은 scanf로 입력했던 값이였죠.


왜? 저 주소로 이동을 하게 된 것 일까요? 만약 값을 덮어 씌우지 않았다면 0xb7e2fa83으로 이동했을 겁니다.




이제 여기서 알아야 하는 것이, SFP와 RET 입니다.


구조를 나타내면 아래와 같습니다.





 


Save Fram Pointer: SFP는 이전 함수에서의 ebp의 값을 저장해 둡니다. 해당 함수가 실행되고 난 후에, 다시 돌아가야 하는데, 돌아갔을 때의 ebp의 주소를 다시 찾아가기 위한 것입니다.


Return: RET는 SFP와 마찬가지로 이전 함수로 돌아가기 위한 주소를 담고 있습니다. 




위와 같은 구조를 가지고 있기 때문에 앞서 값을 넘치게 입력했을 경우 0x36353433으로 이동하게 된 것입니다.



이러한 방법으로 RET 값을 조작해서 system 함수를 호출하거나 프로그램 상에서 호출되지 않는 함수에도 접근이 가능하게 되는 것입니다.



'High Level Technique > System Hacking' 카테고리의 다른 글

Return To Library (RTL)  (2) 2016.04.20
Plt 와 Got  (0) 2016.04.20
Fake EBP  (0) 2016.04.19
main의 SFP는 왜 0이 되는가?  (1) 2016.04.19
Save Frame Pointer Overwrite (SFO)  (0) 2016.04.15