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 |