Skip to content

Instantly share code, notes, and snippets.

@chaelim
Last active December 16, 2015 11:58
Show Gist options
  • Save chaelim/5430872 to your computer and use it in GitHub Desktop.
Save chaelim/5430872 to your computer and use it in GitHub Desktop.
/****************************************************************************
*
* BrokenGuardPage.cpp
*
* Just use following commands for compile:
* cl BrokenGuardPage.cpp
*
* Written by CS Lim (9/26/2006)
*
***/
#include <stdio.h>
#include <process.h>
#include <windows.h>
//===========================================================================
void Crash () {
printf("Crash\n");
// This function simply allocate a big local array and initalizes first element
char test[0x2000];
test[0] = 0;
}
//===========================================================================
static unsigned __stdcall ThreadProc (LPVOID param) {
printf ("ThreadProc\n\tTry to access Stack Guard Page\n");
// param points localVar in AccessStackGuardFromOtherThread function
char * ptr = (char *)param;
ptr -= 0x2000;
volatile char ch = *ptr;
return 0;
}
//===========================================================================
static void AccessStackGuardFromOtherThread () {
printf("AccessStackGuardFromOtherThread\n");
unsigned localVar;
HANDLE exceptionThread = (HANDLE)_beginthreadex(
NULL,
0, // stack size
ThreadProc,
&localVar, // <== Pass the pointer of local variable
0, // suspended = false
NULL
);
// Wait for the thread finish
WaitForSingleObject(exceptionThread, INFINITE);
}
//===========================================================================
static LONG WINAPI OurUnhandledExceptionFilter (EXCEPTION_POINTERS * ep) {
printf ("OurUnhandledExceptionFilter: exception code = %X\n", ep->ExceptionRecord->ExceptionCode);
if (ep->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION)
printf("STATUS_GUARD_PAGE_VIOLATION :%0X\n", ep->ExceptionRecord->ExceptionInformation[1]);
return EXCEPTION_EXECUTE_HANDLER;
}
//===========================================================================
void main () {
// Set our unhandled exception filter to see what exception occurs
// but it's not necessary to demonstrate the problem.
SetUnhandledExceptionFilter(OurUnhandledExceptionFilter);
AccessStackGuardFromOtherThread();
Crash();
printf("End of Program.\n"); // <=== This will never be called
}
@chaelim
Copy link
Author

chaelim commented Apr 30, 2013

Note

This program demonstrates that how just READ access to thread's stack guard page from a different thread can cause access violation.

  1. Thread A creates Thread B and pass pointer of local variable.
  2. Thread B reads a random memory location in the Thread A's stack guard page. It'll cause Thread A's stack guard page exception (STATUS_GUARD_PAGE_VIOLATION) from Thread B and that is not handled properly.
  3. Thread A allocate some large local variable and try to initialize. In normal situation, stack area should be grown to hold the local variable by OS but stack guard page is broken by Thread A so it does not grow. So, boom crash!

What this means?

  • It shows how stack growing mechanism is fragile in especially mulithreaded environment. A subtle bug in one thread that read access to other thread's can crash the application. 1.
  • Allowing PROCESS_VM_READ from you program can lead serious security issue like allowing crash your application from any other apps. 2
  • IsBadxxxPtr API can cause same issue 3
  • .NET commits whole stack memory (no run-time growing). They chose stability by sacrificing more memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment