Skip to content

Instantly share code, notes, and snippets.

@Donpedro13
Created October 26, 2020 18:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Donpedro13/ef146aa9771b42d83b8acdde559abbb8 to your computer and use it in GitHub Desktop.
Save Donpedro13/ef146aa9771b42d83b8acdde559abbb8 to your computer and use it in GitHub Desktop.
size_t __chkstk (size_t stackSpaceSize)
{
// Calculate what the stack pointer would be, if the caller of
// __chkstk simply made its stack allocation instead of
// calling __chkstk.
//
// 0x18: 0x10 for 2 saved registers (used by __chkstk), plus
// 0x8 for the saved return address (__chkstk was call'd)
uintptr_t adjustedSP = __rsp + 0x18 - stackSpaceSize;
// This error handling branch takes care of wraparounds. If the
// stack allocation is so big that it would wrap adjustedSP around,
// adjustedSP is set to zero.
//
// With adjustedSP == 0, the loop at the end of the function will try
// to touch every page from stackLimit to the top of the stack,
// essentially triggering a stack overflow.
if (__rsp + 0x18 > stackSpaceSize)
adjustedSP = 0;
uintptr_t stackLimit =
reinterpret_cast<PNT_TIB> (NtCurrentTeb ())->StackLimit;
// Will the caller's SP reside below the guard area?
if (adjustedSP >= stackLimit) {
// If yes, then no probing needs to be done.
return stackSpaceSize;
}
// If we got here, the caller's SP would skip (the) guard page(s).
// Probing of pages is needed.
// Get to the first byte of the adjusted SP's page by rounding
// down to 4K (a page spans 0x0 - 0xFFF)
uintptr_t firstByteOfLastPage = adjustedSP &= 0xFFFFFFFFFFFFF000;
uintptr_t currentPageToProbe = stackLimit;
do {
// Go "up" a page
uintptr_t currentPageToProbe -= 0x1000;
// Probe the page by writing a zero to it
*reinterpret_cast<char*> (currentPageToProbe) = 0;
} while (currentPageToProbe != firstByteOfLastPage);
return stackSpaceSize;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment