본문 바로가기

Hacking/System Hacking-

[시스템 해킹]버퍼 오버 플로우(Buffer Overflow)



1. 버퍼(Buffer)의 정의 및  버퍼 오버 플로우(Buffer Overflow) 의 정의


버퍼(Buffer) 란 메모리의 조각들, 다시 말해서 데이터를 저장하기 위해 휘발성으로 잠시동안 사용되는 


한정적인 공간입니다.


흔하게 예를들어서 VB와 같은 프로그램으로 프로그래밍시에 버퍼의 크기를 검사하지 않고 프로그래밍할 경우


10KB 라는 할당 되어있는 저장공간이 있으면 이 메모리의 범위를 초과하는 버퍼가 입력되면


할당 된 버퍼 밖의 공간에 쓰기 가 발생하게 되는데


이 경우에 에러가 발생하게 됩니다.


이것을 버퍼 오버플로우 (Buffer Overflow) 라고 합니다.




2. 프로세스의 메모리 구조


버퍼 오버플로우를 이해하기 위해서는 먼저 프로그램의 실행 흐름과 스택(Stack) 의 구조에 대한 이해가 필요합니다.


스택 구조에 대해서는 별도로 포스팅을 하도록 하고, 우선은 표를 보면서 이야기하도록 하죠.


프로그램 실행 시의 메모리 구조를 표로 나타내 보면


하위 주소 (Lower Memory Address)

---------------------

Program Header Table = Text

Text Area

---------------------

Uninitialized Data Area

Initialized Data Area = Data

---------------------

Heap Area = Heap

---------------------

Stack Area = Stack

---------------------

상위 주소 (High Memory Address)




일단 Text Area와 Data Area는 프로그래머 (또는 해커) 가 접근할 수 없다는 것 정도만 알아두시면 됩니다.


그럼 프로그래머가 사용할 수 있는 메모리는 스택과 힙 뿐인데요.


여기서 어떤 메모리 영역을 공격하는가에 따라 스택 오버플로우 (Stack Overflow) 와


힙 오버플로우 (Heap Overflow) 공격으로 나누어지게 됩니다.



이번에는 스택 오버플로우에 대해서만 적어보겠습니다.


3. 스택 오버플로우


3-1. 스택


위에서 살펴본 메모리 레이아웃에서 가장 밑바닥에 쳐박혀 있는 스택(Stack) 을 끌어와 봅시다.


요놈을 뜯어서 자세히 살펴보면


Lower Memory Address

--------------------------- ^

Local Variables |

--------------------------- ^

Stack Frame Pointer (SFP) |

--------------------------- ^ 스택의

Return Address | 증가 방향

--------------------------- ^

Function Arguments |

--------------------------- ^

High Memory Address


이렇게 생겼습니다.


스택은 상위 메모리 주소에서 하위 메모리 주소로 데이터가 저장되므로


스택의 맨 밑바닥에 Function Arguments, 즉 함수 인자들이 깔리고


다음으로 반환 주소 (Return Address, RET),


그 다음은 함수 호출 이전의 프레임을 가리키는 스택 프레임 포인터 (Stack Frame Pointer, SFP),


마지막으로 함수 내에서 선언되는 변수들 (Local Variables) 이 저장됩니다.


반대로, 스택에 저장된 값을 꺼낼 때는 낮은 주소에서 높은 주소의 순서로


즉, Local Variables -> Stack Frame Pointer -> Return Address -> Function Arguments 의 순서로 읽어들이게 됩니다.




3-2. 스택 오버플로우 실전


스택 오버플로우 공격의 타겟은


바로 반환 주소(RET) 를 덮어쓰는 것입니다.


RET는 함수 호출이 끝난 후의 반환 주소를 저장하는 공간입니다.


어떤 함수가 호출되어 정상적으로 수행을 완료하면


RET에 저장된 주소로 프로그램의 실행 흐름이 점프하게 됩니다.


스택 오버플로우는 바로 이것을 노리는 것입니다.


할당된 버퍼의 양보다 큰 공격 코드를 삽입하여 리턴 주소를 덮어써 버리게 되면,


공격자가 프로그램의 실행 흐름을 제어할 수 있게 되기 때문이지요.


셸(Shell)을 따냄으로써 시스템의 권한을 획득하기 위해 셸 코드를 만들고,

이 셸코드를 익스플로잇 코드의 버퍼에 저장한 뒤 버퍼 오버플로우를 통해 RET 주소를 조작하여

셸코드가 저장된 버퍼의 주소로 덮어씌우게 되면 결과적으로 셸코드가 실행되고 시스템 권한을 얻을 수 있게 됩니다.


이를 위해서는 RET 주소까지의 거리를 알아야 하고,

 RET와 RET 이전의 데이터 영역을 한치의 오차도 없이 정확하게 덮어써야만 합니다.

 공격 수행 후에 RET 주소가 해커의 의도대로 정확히 변조되어야 하며, 조금이라도 실수가 있었다면 공격은 실패합니다.


그럼, 설명은 이쯤 하고 스택 오버플로우 공격의 절차를 알아봅시다.


리눅스 기준입니다.


1. 공격 셸 코드를 버퍼에 저장한다.


2. 루트 권한으로 실행되는 프로그램의 특정 함수의 스택의 반환 주소의 버퍼를 오버플로우시켜서 공격 셸 코드가 저장되어 있는 버퍼의 주소로 덮어씌운다.


3. 특정 함수의 호출이 완료되면 조작된 반환 주소로 셸 코드의 주소가 반환되고, 셸 코드가 실행되어 루트 권한을 획득하게 된다.





한때 네이트온 사용자들의 일부가 사용했던 공격 기법입니다.


네이트온의 쪽지 메세지에 오버플로우 공격을 실행하여


쪽지를 받는사람은 네이트온이 시스템상에서 강제종료 되도록 유도하였습니다.


네이트온이 웹과 연동되어있다는 점을 생각하여


http://note.nate.com/web/send/WrteAction.do?font_name=Gulime&font_syle=font_size=1000000000000000000000000pt&font_color=!000000&body=여기에메세지&from=writeForm&receiver=받는 사람 ID


이런식으로 보내게되면 


기본적인 글자 사이즈(폰트 사이즈)를 넘어버린 1000000000000000000000000000 이라는 숫자를 감당하지 못하고 


네이트온이 시스템 상에서 종료되어 버리는 것입니다.



Write By. CISA

* 상단 스택 구조 및 메모리 구조 TERA  블로그 일부 인용