[Win32SS] Form Sanity to Hook Callbacks

Fix WH_CALLWNDPROC/RET data to user hook calls. See CORE-13019 and CORE-13907.
This commit is contained in:
jimtabor 2020-03-28 14:18:14 -05:00
parent d8add40e89
commit 915a5764a9
3 changed files with 69 additions and 36 deletions

View file

@ -61,6 +61,7 @@ typedef struct _HOOKPROC_CALLBACK_ARGUMENTS
ULONG_PTR offPfn;
BOOLEAN Ansi;
LRESULT Result;
UINT lParamSize;
WCHAR ModuleName[512];
} HOOKPROC_CALLBACK_ARGUMENTS, *PHOOKPROC_CALLBACK_ARGUMENTS;
@ -72,6 +73,20 @@ typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
/* WCHAR szClass[] */
} HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS, *PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS;
typedef struct tagCWP_Struct
{
HOOKPROC_CALLBACK_ARGUMENTS hpca;
CWPSTRUCT cwps;
PBYTE Extra[4];
} CWP_Struct, *PCWP_Struct;
typedef struct tagCWPR_Struct
{
HOOKPROC_CALLBACK_ARGUMENTS hpca;
CWPRETSTRUCT cwprs;
PBYTE Extra[4];
} CWPR_Struct, *PCWPR_Struct;
typedef struct _EVENTPROC_CALLBACK_ARGUMENTS
{
HWINEVENTHOOK hook;

View file

@ -509,6 +509,8 @@ co_IntLoadDefaultCursors(VOID)
return TRUE;
}
static INT iTheId = -2; // Set it out of range.
LRESULT APIENTRY
co_IntCallHookProc(INT HookId,
INT Code,
@ -535,6 +537,8 @@ co_IntCallHookProc(INT HookId,
PMSG pMsg = NULL;
BOOL Hit = FALSE;
UINT lParamSize = 0;
CWPSTRUCT* pCWP = NULL;
CWPRETSTRUCT* pCWPR = NULL;
ASSERT(Proc);
/* Do not allow the desktop thread to do callback to user mode */
@ -593,27 +597,27 @@ co_IntCallHookProc(INT HookId,
goto Fault_Exit;
}
break;
case WH_KEYBOARD_LL:
case WH_KEYBOARD_LL:
ArgumentLength += sizeof(KBDLLHOOKSTRUCT);
break;
case WH_MOUSE_LL:
case WH_MOUSE_LL:
ArgumentLength += sizeof(MSLLHOOKSTRUCT);
break;
case WH_MOUSE:
case WH_MOUSE:
ArgumentLength += sizeof(MOUSEHOOKSTRUCT);
break;
case WH_CALLWNDPROC:
{
CWPSTRUCT* pCWP = (CWPSTRUCT*) lParam;
ArgumentLength += sizeof(CWPSTRUCT);
pCWP = (CWPSTRUCT*) lParam;
ArgumentLength = sizeof(CWP_Struct);
lParamSize = lParamMemorySize(pCWP->message, pCWP->wParam, pCWP->lParam);
ArgumentLength += lParamSize;
break;
}
case WH_CALLWNDPROCRET:
{
CWPRETSTRUCT* pCWPR = (CWPRETSTRUCT*) lParam;
ArgumentLength += sizeof(CWPRETSTRUCT);
pCWPR = (CWPRETSTRUCT*) lParam;
ArgumentLength = sizeof(CWPR_Struct);
lParamSize = lParamMemorySize(pCWPR->message, pCWPR->wParam, pCWPR->lParam);
ArgumentLength += lParamSize;
break;
@ -647,6 +651,7 @@ co_IntCallHookProc(INT HookId,
Common->Mod = Mod;
Common->offPfn = offPfn;
Common->Ansi = Ansi;
Common->lParamSize = lParamSize;
RtlZeroMemory(&Common->ModuleName, sizeof(Common->ModuleName));
if (ModuleName->Buffer && ModuleName->Length)
{
@ -697,25 +702,27 @@ co_IntCallHookProc(INT HookId,
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
break;
case WH_CALLWNDPROC:
{
PCWP_Struct pcwps = (PCWP_Struct)Common;
RtlCopyMemory( &pcwps->cwps, pCWP, sizeof(CWPSTRUCT));
/* For CALLWNDPROC and CALLWNDPROCRET, we must be wary of the fact that
* lParam could be a pointer to a buffer. This buffer must be exported
* to user space too */
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
if(lParamSize)
if ( lParamSize )
{
RtlCopyMemory(Extra + sizeof(CWPSTRUCT), (PVOID)((CWPSTRUCT*)lParam)->lParam, lParamSize);
((CWPSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
RtlCopyMemory( &pcwps->Extra, (PVOID)pCWP->lParam, lParamSize );
}
}
break;
case WH_CALLWNDPROCRET:
RtlCopyMemory(Extra, (PVOID) lParam, sizeof(CWPRETSTRUCT));
Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
if(lParamSize)
{
PCWPR_Struct pcwprs = (PCWPR_Struct)Common;
RtlCopyMemory( &pcwprs->cwprs, pCWPR, sizeof(CWPRETSTRUCT));
if ( lParamSize )
{
RtlCopyMemory(Extra + sizeof(CWPRETSTRUCT), (PVOID)((CWPRETSTRUCT*)lParam)->lParam, lParamSize);
((CWPRETSTRUCT*)Extra)->lParam = (LPARAM)lParamSize;
RtlCopyMemory( &pcwprs->Extra, (PVOID)pCWPR->lParam, lParamSize );
}
}
break;
case WH_MSGFILTER:
case WH_SYSMSGFILTER:
@ -745,7 +752,11 @@ co_IntCallHookProc(INT HookId,
if (!NT_SUCCESS(Status))
{
ERR("Failure to make Callback! Status 0x%x\n",Status);
if ( iTheId != HookId ) // Hook ID can change.
{
ERR("Failure to make Callback %d! Status 0x%x\n",HookId,Status);
iTheId = HookId;
}
goto Fault_Exit;
}
@ -1216,12 +1227,13 @@ APIENTRY
co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize )
{
NTSTATUS Status;
PVOID ResultPointer;
Status = KeUserModeCallback(USER32_CALLBACK_UMPD,
pkt,
InSize,
pvOutData,
(PULONG)&OutSize);
Status = KeUserModeCallback( USER32_CALLBACK_UMPD,
pkt,
InSize,
&ResultPointer,
(PULONG)&OutSize );
if (!NT_SUCCESS(Status))
@ -1230,6 +1242,8 @@ co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize
return 1;
}
if (OutSize) RtlMoveMemory( pvOutData, ResultPointer, OutSize );
return 0;
}

View file

@ -699,35 +699,39 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
_SEH2_END;
break;
case WH_CALLWNDPROC:
// ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT));
{
PCWP_Struct pcwps = (PCWP_Struct)Common;
CWPSTRUCT *pCWPT = &pcwps->cwps;
pCWP = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPSTRUCT));
RtlCopyMemory(pCWP, pCWPT, sizeof(CWPSTRUCT));
// ERR("WH_CALLWNDPROC: Code %d, wParam %d msg %d\n",Common->Code,Common->wParam,pCWP->message);
/* If more memory is reserved, then lParam is a pointer.
* Size of the buffer is stocked in the lParam member, and its content
* is at the end of the argument buffer */
if(ArgumentLength > (sizeof(CWPSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
if ( Common->lParamSize )
{
RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT),
(PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT),
pCWP->lParam);
pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize );
}
Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
HeapFree(GetProcessHeap(), 0, pCWP);
}
break;
case WH_CALLWNDPROCRET:
/* Almost the same as WH_CALLWNDPROC */
pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT));
if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
{
PCWPR_Struct pcwprs = (PCWPR_Struct)Common;
CWPRETSTRUCT *pCWPRT = &pcwprs->cwprs;
pCWPR = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPRETSTRUCT));
RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT));
if ( Common->lParamSize )
{
RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT),
(PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT),
pCWPR->lParam);
pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize );
}
Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
HeapFree(GetProcessHeap(), 0, pCWPR);
}
break;
case WH_MSGFILTER: /* All SEH support */
case WH_SYSMSGFILTER: