[WinDbg] Stack Overrun
/GS 플래그가 지정되었을때 함수 호출부와 함수 끝부분에서 쿠키값을 비교.
비교결과 틀리게 되면 해당 함수부의 지역변수의 영역을 넘어섰음을 의미한다.
따라서 특정 함수의 마지막부분을 가리키면서 해당 오류코드를 뱉어낸다면
함수 부분에서 지역변수를 넘어설 수 있는 지점을 하나씩 주석처리해 가면서 찾는다.
좋은 습관은 방어코딩이다.
나의 경우는 다음과 같은 것이었다.
filepath[512];
wcscpy(
filepath, objectName.Buffer, objectName.Length / 2 ); <--
objectName.Length/2가 항상 512보다 작다는 것을 보장할 수 있나? 보장할 수 없기 때문에 최악의 경우 넘어서지
않도록 조치를 해줘야 한다. wcscpy_s류 같은 것들을 쓰자
gflags.exe를 이용한 디버깅 방법
일단 OS한테 특정 process에 대해서 user stack trace을 설정해 줘야 한다. 두가지 방법이 있는데
gflags.exe를 이용한 디버깅 방법
일단 OS한테 특정 process에 대해서 user stack trace을 설정해 줘야 한다. 두가지 방법이 있는데
첫째는) gflags.exe를 이용하는 거고
둘째는) 커맨드 창에서 gflags.exe /i TestProgram.exe +ust 입력
결국, gflags.exe가 위의 명령의 결과로 다음의 레지스트리에 키값을 생성해 준다.
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution
키값 TestProgram.exe
GlobalFlag RGB_SZ 0x1000
위처럼 OS flag를 설정한 후에 process 를 시작해야 하는 거고
이후에 windbg를 기동한 후에 해당 process 를 attach 한다.
테스트 프로그램1) Heap Block을 넘어선 Free
---------------------------------------
char* p1 = (char*)malloc( 0x10 );
char* p2 = (char*)malloc( 0x20 );
sprintf( p1, "%s", "0123456789ABCDE0123456789ABCDE" );
OutputDebugStringA( p1 );
SAFE_FREE(p1);
---------------------------------------
위와 같이 되어 있는 상태에서
gflags.exe 설정없이 Windbg로 실행하고 나면 windbg는 명령창에 다음을 출력해 준다.
gflags.exe 설정없이 Windbg로 실행하고 나면 windbg는 명령창에 다음을 출력해 준다.
Heap block at 00B35918 modified at 00B35930 past requested size of 10
Heap block의 처음 8바이트는 힙 메타데이터이고(00B35918)
그
이후부터가 우리한테 할당된 부분이기 때문에 00B35920부터가 우리가 볼수 있는 영역이다. 그리고 명령에서 0x10바이트를
할당했기 때문에 00B35930-1까지가 접근할 수 있는 영역이다.
위에서 그런 내용을 표시해 주고 있는 거다.
(WINDBG를 attach해서 실행하는 것 만으로도 어느정도는 보여주고 있다)
위에서 그런 내용을 표시해 주고 있는 거다.
(WINDBG를 attach해서 실행하는 것 만으로도 어느정도는 보여주고 있다)
00b35918 86 45 13 67 62 f0 00 18-30 31 32 33 34 35 36 37 .E.gb...01234567
00b35928 38 39 41 42 43 44 45 30-31 32 33 34 35 36 37 38 89ABCDE012345678
00b35938 39 41 42 43 44 45
테스트 프로그램2) Stack Overrun / Heap Overrun
---------------------------------------
WCHAR* pw = L"012345678901234567890123456789";
wprintf(L"Press any key to start\n");
_getch();
HelperFunction(pw); <- Stack Overrun
DupString(pw); <-
VOID HelperFunction(WCHAR* psz)
{
WCHAR pszCopy[30];
wcscpy(pszCopy, psz);
OutputDebugStringW(pszCopy);
}
BOOL DupString(WCHAR* psz)
{
BOOL bRet=FALSE;
if(psz!=NULL)
{
DWORD dwBytes = 10 * sizeof(WCHAR);
pszCopy = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, dwBytes);
if(pszCopy)
{
wcscpy(pszCopy, psz);
wprintf(L"Copy of string: %s", pszCopy);
HeapFree(GetProcessHeap(), 0, pszCopy);
bRet=TRUE;
}
}
return bRet;
}
---------------------------------------
마찬가지로 위와 같이 되어 있는 상태에서 Windbg로 실행하기만 하면 아래와 같은 정보를 준다. HelperFunction()을 호출하는 경우는 아래 (Stack 상의 유효 범위를 오버해 버린 경우)
STATUS_STACK_BUFFER_OVERRUN encountered
DupString()을 호출하는 경우은 아래( Heap 상의 유효 범위를 오버해 버린 경우)
Heap block at 004D36E0 modified at 004D36FC past requested size of 14
총 2바이트짜리 10개니깐, 0x14 바이트가 유효 범위이다.
우리가 볼수 있는 영역은 004D36E8부터 이고 004D36E8+0x14-1(004D36FB) 까지이다.
우리가 볼수 있는 영역은 004D36E8부터 이고 004D36E8+0x14-1(004D36FB) 까지이다.
Windbg가 친절하게도 004D36FC를 넘었다고 해주고 있고, 요청된 사이즈도 0x14바이트라는 것을 알려주고 있다.
여기까지는 명시적으로 Stack과 Heap에 대해서 overrun 혹은 free시 Windbg가 영리하게 detect를 해줌을 확인할 수가 있다
댓글
댓글 쓰기