Skip to content

Instantly share code, notes, and snippets.

@rbmm
Created September 22, 2025 11:57
Show Gist options
  • Select an option

  • Save rbmm/40528e3add769160e3964cc121af0aca to your computer and use it in GitHub Desktop.

Select an option

Save rbmm/40528e3add769160e3964cc121af0aca to your computer and use it in GitHub Desktop.
struct TPARAMS
{
HANDLE hEvent;
PNT_TIB Tib;
ULONG_PTR LowLimit, HighLimit;
};
ULONG WINAPI TestThread(TPARAMS* param)
{
param->Tib = reinterpret_cast<PNT_TIB>(NtCurrentTeb());
GetCurrentThreadStackLimits(&param->LowLimit, &param->HighLimit);
return NtSignalAndWaitForSingleObject(param->hEvent, NtCurrentThread(), TRUE, 0);
}
// Rsp must be in [StackLimit - 0x1000, StackBase]
void testSetContext()
{
TPARAMS param;
if (param.hEvent = CreateEventW(0, 0, 0, 0))
{
if (HANDLE hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)TestThread, &param, 0, 0))
{
if (WAIT_OBJECT_0 == WaitForSingleObject(param.hEvent, INFINITE))
{
CONTEXT ctx {};
ctx.ContextFlags = CONTEXT_CONTROL;
if (0 <= ZwGetContextThread(hThread, &ctx))
{
ULONG_PTR Rsp = ctx.Rsp;
if (param.HighLimit != (ULONG_PTR)param.Tib->StackBase)
{
__debugbreak();
}
ctx.Rsp = param.HighLimit;
ZwSetContextThread(hThread, &ctx);
// rsp <= StackBase must be !
ctx.Rsp += sizeof(PVOID);
ZwSetContextThread(hThread, &ctx);
ctx.Rsp = (ULONG_PTR)param.Tib->StackLimit;
if (0 <= ZwSetContextThread(hThread, &ctx))
{
if (param.LowLimit <= (ULONG_PTR)param.Tib->StackLimit)
{
NTSTATUS status;
ULONG_PTR a = param.LowLimit / sizeof(PVOID), b = (ULONG_PTR)param.Tib->StackLimit / sizeof(PVOID), o;
while (a < b)
{
ctx.Rsp = (o = (a + b) >> 1) * sizeof(PVOID);
0 > (status = ZwSetContextThread(hThread, &ctx)) ? a = o + 1 : b = o;
}
DbgPrint("StackLimit - %x\n", (ULONG_PTR)param.Tib->StackLimit - ctx.Rsp);
}
}
PVOID StackBase = param.Tib->StackBase;
PVOID StackLimit = param.Tib->StackLimit;
param.Tib->StackLimit = (PVOID)0x12345000;
ctx.Rsp = 0x12345800;
param.Tib->StackBase = (PVOID)0x12346000;
ZwSetContextThread(hThread, &ctx);
param.Tib->StackLimit = StackLimit;
param.Tib->StackBase = StackBase;
ctx.Rsp = Rsp;
ZwSetContextThread(hThread, &ctx);
}
ZwAlertThread(hThread);
}
WaitForSingleObject(hThread, INFINITE);
NtClose(hThread);
}
NtClose(param.hEvent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment