본문 바로가기

3. Pwnable (포너블)/2) 개념 정리

[2020.11.14] 4너블 4ever - 달고나 문서 58p ~ 70p

-malloc()로 만들어진 메모리 공간은 힙(heap)에 만들어진다.

 (힙은 스텍과 달리 낮은 메모리 주소에서 높은 메모리 주소 방향으로 할당된다.)

 

- get_esp()

어셈블리 코드를 이용하여 ESP 레지스터가 가리키는 곳의주소를 EAX레지스터에 넣는   역할을 한다.(이것 만으로 EAX레지스터의 값이 리턴됨.)

*대부분의 프로그램들의 스택 시작점은 같다

 

-EGG라는 새로운 환경변수가 생성 -> 스텍 세그면트의 상단에 등록된 환경 변수들의 크기가 커짐 -> main 함수의 base pointer는 그만큼 낮은 곳에 자리잡게 됨.

EGG안에는 많은 NOP들이 들어있다.

이 NOP가 있어서 구해진 stack pointer가 쉘 코드의 정확한 시작점을 가리키지 않더라도 instruction pointer가 흘러서 쉘 코드 시작점까지 도달할 수 있게된다. 그래서 return address의 대체값으로 활용될 수 있다.

 

 

- 위에서 환경변수가 잘 들어가 있다는 것을 확인할 수 있다.

- 다음으로 프로그램 vul에서 어느 지점에 return address가 있는지 확인해야 하고 거기에 구해진 stack pointer의 값을 넣어야 한다.

 

공격

먼저 버퍼의 크기부터 가늠한다.

vul.c

- 위 vul.c 소스코드에서는 1024 바이트의 배열을 만들었지만 gcc가 8바이트 dummy를 추가하여 총 1032 바이트만큼 스택이 확장 되었다. 

- 따라서 이전 함수의 base pointer(SFP)가 저장되는 4바이트를 고려한다면 1036 바이트를 채우고 그 이후 4바이트에 return address가 들어가 있을 것이다.

 

1024(buffer) + 8(dummy) + 4(sfp:이전 함수의 base pointer) + 4(return address) 

 

버퍼오버플로우 공격 과정

- little endian 정렬방식

 

버퍼 오버플로 공격 과정의 디버그

- eggshell이 출력한 stack pointer는 return address를 덮어 쓸 EGG 위치를 나타내고 있다. 

- gdb를 이용해 취약 프로그램 vul을 실행하고 두 개의 breakpoint를 지정하였다.

- ebp를 확인해보니 eggshell이 출력한 0xbffffa58보다 작은 값이므로 EGG가 환경 변수 영역에 들어있다는 것이 확인되었다.

 

- eggshell이 출력한 주소값에 어떤 데이터가 저장되어 있는지 확인하면 NOP가 위치하고 있음을 알 수 있다. 

- 다음으로 return address를 확인한다. ebp(0xbfffee78)에는 이전 함수의 base pointer가 들어 있고, return address는 ebp보다 4바이트 위에 있을 것이므로 ebp+4(0xbfffee7c)를 확인하면 0x4003456d가 들어있다.

- 이후 실행을 계속해 buffer를 overflow 시킨다. 그 다음 return address를 확인해보면 0xbffffa58로 바뀐 것을 확인할 수 있다.

- 0xbffffa58는 return address를 덮어쓰기 위해 구한 EGG의 위치이다. 따라서 main 함수가 실행을 마치고 return 될 때 EIP는 EGG가 있는 시점을 가리키게 될 것이고 쉘 코드가 수행되어 root 권한의 쉘이 뜨는 것이다.