Smashing the Stack Example
각각의 쓰레드는 stack memory를 사용합니다. 스택은 아래방향으로 자랍니다. 만약 호출된 함수가 또 다른 함수를 호출하면 스택은 더 작은 메모리 주소값으로 확장됩니다. 스택 메모리에는 static 변수가 아닌 임시적으로 사용하는 변수나 parameter value, return address등이 포함되어 있습니다. 만약 버퍼가 몇몇 데이타(user의 input variable 등)보다 너무 작으면 다른 stack variable들이나 심지어는 return address 까지 덮어쓸 가능성이 있습니다. Stack contents와 automatic variable의 정확한 layout은 아키텍쳐와 컴파일러에 따라 다릅니다. 하지만 약간의 조사를 통해 특정한 아키텍쳐에서 어떻게 스택을 부술수 있는지 배울 수 있습니다.
아래의 예는 스택에 return address가 어떻게 저장되는지를 보여줍니다. 특정한 32비트 아키텍쳐인 Live Linux Machine에서, return address는 automatic variable의 주소보다 2 pointer(즉, 8 byte)전에 저장됩니다. 이 코드에서는 의도적으로 스택 값을 변경하여 input fuction이 return될 때 메인 함수로 돌아가는 것이 아니라 exploit function으로 return됩니다.
// Overwrites the return address on the following machine: // http://cs-education.github.io/sys/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> void breakout() { puts("Welcome. Have a shell..."); system("/bin/sh"); } void input() { void *p; printf("Address of stack variable: %p\n", &p); printf("Something that looks like a return address on stack: %p\n", *((&p)+2)); // Let's change it to point to the start of our sneaky function. *((&p)+2) = breakout; } int main() { printf("main() code starts at %p\n",main); input(); while (1) { puts("Hello"); sleep(1); } return 0; }
위 메인 함수에서 input 함수를 호출하는데, 이 input의 return address가 breakout으로 바뀌어 breakout 함수가 호출되어 system함수로 shell을 실행하고 있습니다. 이 문제를 해결하는데는 다양한 방법이 있습니다.
'Angrave System Programming > Memory and Allocators' 카테고리의 다른 글
Implementing a Memory Allocator (0) | 2019.01.07 |
---|---|
Heap Memory Introduction(2) (0) | 2019.01.04 |
Heap Memory Introduction(1) (0) | 2019.01.04 |