Skip to content

Instantly share code, notes, and snippets.

@wbenny
Last active August 5, 2024 05:01
Show Gist options
  • Save wbenny/0d2269a8ae93c420d013632dc2cd432f to your computer and use it in GitHub Desktop.
Save wbenny/0d2269a8ae93c420d013632dc2cd432f to your computer and use it in GitHub Desktop.
//
// NtContinueEx is now used by ntdll!KiUserApcDispatcher.
// The KCONTINUE_ARGUMENT structure is built in the KiInitializeUserApc
// function.
//
typedef enum _KCONTINUE_TYPE
{
KCONTINUE_UNWIND,
KCONTINUE_RESUME,
KCONTINUE_LONGJUMP,
KCONTINUE_SET,
KCONTINUE_LAST,
} KCONTINUE_TYPE;
typedef struct _KCONTINUE_ARGUMENT
{
KCONTINUE_TYPE ContinueType;
ULONG ContinueFlags;
ULONGLONG Reserved[2];
} KCONTINUE_ARGUMENT, *PKCONTINUE_ARGUMENT;
#define KCONTINUE_FLAG_TEST_ALERT 0x00000001
#define KCONTINUE_FLAG_DELIVER_APC 0x00000002
NTSYSCALLAPI
NTSTATUS
NTAPI
NtContinue(
_In_ PCONTEXT ContextRecord,
_In_ BOOLEAN TestAlert
)
{
NtContinueEx(ContextRecord, (PCONTINUE_ARGUMENT)TestAlert);
}
NTSYSCALLAPI
NTSTATUS
NTAPI
NtContinueEx(
_In_ PCONTEXT ContextRecord,
_In_ PKCONTINUE_ARGUMENT ContinueArgument
)
{
KiContinueEx(ContextRecord, ContinueArgument, <rsp>, <rbp-128>);
}
NTSTATUS
NTAPI
RtlContinueLongJump(
_In_ PCONTEXT ContextRecord
)
{
KCONTINUE_ARGUMENT ContinueArgument;
RtlZeroMemory(&ContinueArgument, sizeof(KCONTINUE_ARGUMENT));
ContinueArgument.ContinueType = KCONTINUE_LONGJUMP;
return NtContinueEx(ContextRecord, &ContinueArgument);
}
NTSTATUS
NTAPI
KiContinueEx(
_In_ PCONTEXT ContextRecord,
_In_ PKCONTINUE_ARGUMENT ContinueArgument, // previously: BOOLEAN TestAlert
_In_ PKEXCEPTION_FRAME ExceptionFrame,
_In_ PKTRAP_FRAME TrapFrame
)
{
//
// 2nd argument was previously "BOOLEAN TestAlert"... but in fact, it still is!
// KiContinueEx checks if the ContinueArgument is <= 0xFF, if it is, it treats it
// as a BOOLEAN. If its larger, then it treats it as PCONTINUE_ARGUMENT.
//
// This also means you can use NtContinueEx as if it was NtContinue - that is, provide
// it second "BOOLEAN TestAlert" parameter instead of KCONTINUE_ARGUMENT.
//
// Keep in mind that this code is rough incomplete description.
//
PKTHREAD CurrentThread = KeGetCurrentThread();
BOOLEAN TestAlert;
...
if ((ULONG_PTR)ContinueArgument <= 0xFF)
{
TestAlert = (BOOLEAN)ContinueArgument;
}
else
{
TestAlert = !!(ContinueArgument->ContinueFlags & KCONTINUE_FLAG_TEST_ALERT);
DeliverApc = !!(ContinueArgument->ContinueFlags & KCONTINUE_FLAG_DELIVER_APC);
}
if (TestAlert)
{
KeTestAlertThread(UserMode);
}
if (DeliverApc)
{
TrapFrame->ContextRecord = (ULONG_PTR)ContextRecord;
TrapFrame->ExceptionFrame = (ULONG_PTR)ExceptionFrame;
KiDeliverApc(UserMode, 0, TrapFrame);
...
}
...
}
ULONGLONG
NTAPI
KiInitializeUserApc(
_In_ PKEXCEPTION_FRAME ExceptionFrame,
_In_ PKTRAP_FRAME TrapFrame,
_In_ PKNORMAL_ROUTINE NormalRoutine,
_In_ PVOID NormalContext,
_In_ PVOID SystemArgument1,
_In_ PVOID SystemArgument2,
_In_ BOOLEAN TestAlert // New argument
)
{
...
RtlZeroMemory(ContinueArgument, sizeof(KCONTINUE_ARGUMENT));
ContinueArgument->ContinueType = KCONTINUE_RESUME;
ContinueArgument->ContinueFlags = KCONTINUE_FLAG_DELIVER_APC;
if (TestAlert)
{
ContinueArgument->ContinueFlags |= KCONTINUE_FLAG_TEST_ALERT;
}
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment