• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

아래분과 비슷한 질문인데 답변을 듣고도 이해가 가지 않는 부분이 있어 질문 드립니다.

22.03.25 12:37 작성 조회수 156

0

// 스택 프레임 [ 지역변수 ] a가 함수가 종료되면서 없어지는데 함수 반환을 지역변수 a의 주소값으로 하고 있다.
int* TestPtr() {

	int a = 3;
	return &a;
}

// TestWrong() 함수가 호출되면서 다시 한번 스택프레임이 쌓이는데 이때 그전에 사용되고 반납됐던, TestPtr() 스택프레임 부분이 재사용되게 되고,
// a[0] ~ a[99] 까지 100개의 int(4byte)가 스택프레임 [지역변수] 에 쌓이고 [매개변수]로 받은 ptr이 가리키는 값을 다시한번 0x12341234로 수정한다.
void TestWrong(int* ptr) {
	int a[100] = {};
	a[99] = 0xAAAAAAAA;
	*ptr = 0x12341234;
}

int main() {

	// TestPtr() 스택프레임의 지역변수 a의 주소를 리턴받고
	int* ptr = TestPtr();

	// TestPtr 호출이 종료되면서 스택프레임에 있는 a의 주소 값이 유효하지 않게 되는데, 엄밀히 말하면 메모리 입장에서는 사라지는게 아니고 스택프레임 관리 차원에서 esp를 땡겨주는것이기 때문에
	// ptr에 담긴 값을 수정할 수 있다.  ( 이 자체만으로도 치명적인 문제! 하지만 디버깅에 문제없이 작동된다. )  
	*ptr = 123;

	TestWrong(ptr);

	return 0;
}

 

제가 이해가 안가는 부분은

*ptr = 0x12341234;

가 디버깅 단계에서 오류가 나는 부분입니다.

 

TestPtr() 이 사용했던 스택프레임을 재사용하다 운이 나빠 ptr의 주소가 TestWrong()  스택프레임의 지역변수 a배열 마지막 a[99] 다음인 ( a[99] + 1 ) 에 있다고  하더라도

그 ptr을 수정하는게 TestWrong() 스택프레임과 관련이 없는거 아닌가요?

마치  main 함수 내에서  유효하지 않더라도 

*ptr = 123; 
을 수정했던것처럼요.

제가 놓치고 있는 부분이 있을까요?

계속 고민해도 갈피가 잡히질 않네요..

 

 

답변 1

답변을 작성해보세요.

1

오염된 메모리를 고치는 순간,
사실 그 이후로는 무슨 일이든 일어날 수 있으니
크래시가 나지 않는다고 문제 없다고 판단하면 안 됩니다.
강의 예제에서 *ptr = 123;은 문제 없었고 그 다음 *ptr = 0x123124;가 터졌지만,
거꾸로 되더라도 전혀 이상하지 않습니다.

스택 메모리리는 여전히 유효한 공간이라 메모리를 고쳐쓸 수 있지만,
하필 그 위치가 ebp, ret 주소같이 매우 중요하고 치명적인 데이터가 있던 장소라거나,
디버깅 모드에서 0xCCCCC 쓰레기값으로 채워넣어 오버플로우 여부를 탐지하고 있던 장소라거나,
아니면 다른 포인터(주소)를 저장하고 있는 민감한 장소였다거나,
한다면 그 이후 진행에서 당연히 오동작 할테니 프로그램이 뻗는 것이죠.

김지일님의 프로필

김지일

질문자

2022.03.25

드디어 이해가 갔습니다!!!
감사합니다 :) 

제가 착각하고 있었습니다.

이미 사라진 스택프레임에 있던 ptr을 수정하는것도 문제지만 수정했는데 그게 하필 새롭게 생긴 스택프레임의 오버플로우 여부를 탐지하고 있던 장소와 같이 중요한 장소였으면 디버그 차원에서 프로그램이 뻗게 되는거군요.

다시한번 감사합니다~!
속 시원하게 다음 강의로 가보겠습니다 :)