Only On Win10 32bit Ver 1903, Blue screen error, Stack Overflow while calling ZwOpenProcess routine.

I Registered callback routine by PsSetCreateProcessNotifyRoutine routine to monitor process created/deleted in my Driver.

In this callback routine ZwOpenProcess is used. It works on all wint 10 OS version of 32 and 64 bit but only on latest Win10 32bit Ver 1903, Blue screen error occurred with Stack Overflow log while calling ZwOpenProcess routine.

===
STACKUSAGE_IMAGE: The module at base 0xFFFFFFFFA3020000 was blamed for the stack overflow. It is using 3304 bytes of stack.

STACK_TEXT:
nt!ExpAcquireResourceSharedLite+0x6e
nt!ExAcquireResourceSharedLite+0x3b
nt!ObpCreateHandle+0x734
nt!PsOpenProcess+0x454
nt!NtOpenProcess+0x2c
nt!KiSystemServicePostCall
nt!ZwOpenProcess+0x11
WdFilter!MpGetProcessById+0x6b
WdFilter!MpObSendOpenProcessBMNotification+0x37e
WdFilter!MpObHandleOpenProcessCallback+0x2be
WdFilter!MpObPreOperationCallback+0x32
nt!ObpCallPreOperationCallbacks+0xee
nt!ObpCreateHandle+0xa69
nt!PsOpenProcess+0x454
nt!NtOpenProcess+0x2c
nt!KiSystemServicePostCall
nt!ZwOpenProcess+0x11
MyFilter!GetProcessNameFromId+0x44
MyFilter!MyCreateProcessNotificationRoutine+0x1dd
nt!PspCallProcessNotifyRoutines+0x1c6

Please suggest me, how to deal with this issue ?

Do you have big buffers on the stack? Please provide the output of kf.

Also, why are you not using PsSetCreateProcessNotifyRoutineEx?

Q1: Do you have big buffers on the stack?
No. We didn’t have big buffers on the stack.
(As I mentioned before, It is working on all windows OS (XP,Vista,Win7,Win8.1,Win10) and 32 and 64 Bits but failed with above error only on
Win10 32bit build 1903.)

Q2: Please provide the output of kf.

0: kd> kF
*** Stack trace for last set context - .thread/.cxr resets it

Memory ChildEBP RetAddr

00 a8d69038 82636bab nt!ExpAcquireResourceSharedLite+0x6e
01 10 a8d69048 82965a64 nt!ExAcquireResourceSharedLite+0x3b
02 f0 a8d69138 8296e364 nt!ObpCreateHandle+0x734
03 70c a8d69844 8296df08 nt!PsOpenProcess+0x454
04 1c a8d69860 8277628b nt!NtOpenProcess+0x2c
05 0 a8d69860 82763bf5 nt!KiSystemServicePostCall
06 88 a8d698e8 86974485 nt!ZwOpenProcess+0x11
07 5c a8d69944 86968038 WdFilter!MpGetProcessById+0x6b
08 64 a8d699a8 86967a5e WdFilter!MpObSendOpenProcessBMNotification+0x37e
09 48 a8d699f0 86967464 WdFilter!MpObHandleOpenProcessCallback+0x2be
0a 8 a8d699f8 8296ed9e WdFilter!MpObPreOperationCallback+0x32
0b 44 a8d69a3c 82965d99 nt!ObpCallPreOperationCallbacks+0xee
0c f0 a8d69b2c 8296e364 nt!ObpCreateHandle+0xa69
0d 70c a8d6a238 8296df08 nt!PsOpenProcess+0x454
0e 1c a8d6a254 8277628b nt!NtOpenProcess+0x2c
0f 0 a8d6a254 82763bf5 nt!KiSystemServicePostCall
10 88 a8d6a2dc a3020d0c nt!ZwOpenProcess+0x11
11 40 a8d6a31c a3021479 MYFilter!GetProcessNameFromId+0x44
12 ca8 a8d6afc4 829ba7f6 MYFilter!MYCreateProcessNotificationRoutine+0x1dd
13 60 a8d6b024 829bf034 nt!PspCallProcessNotifyRoutines+0x1c6
14 70 a8d6b094 829a31f4 nt!PspInsertThread+0x4c4
15 7e4 a8d6b878 8277628b nt!NtCreateUserProcess+0x7c4
16 0 a8d6b878 827644a1 nt!KiSystemServicePostCall
17 a4 a8d6b91c a31a6e59 nt!ZwCreateUserProcess+0x11
18 e4 a8d6ba00 a31a6b87 condrv!CdpCreateProcess+0xe9
19 8c a8d6ba8c a31a728f condrv!CdpLaunchServerProcess+0xf7
1a 1c a8d6baa8 8295c04f condrv!CdpFastIoDeviceControl+0x13f
1b 110 a8d6bbb8 829fadea nt!IopXxxControlFile+0x2df
1c 2c a8d6bbe4 8277628b nt!NtDeviceIoControlFile+0x2a
1d 0 a8d6bbe4 774d1570 nt!KiSystemServicePostCall
1e 02f9e9a4 774cfd3a ntdll!KiFastSystemCallRet
1f 4 02f9e9a8 74fc7e9d ntdll!NtDeviceIoControlFile+0xa
20 40 02f9e9e8 74fc7d22 KERNELBASE!ConsoleLaunchServerProcess+0x54
21 280 02f9ec68 74f7b424 KERNELBASE!ConsoleAllocate+0xcf
22 38 02f9eca0 74f7afa0 KERNELBASE!ConsoleInitialize+0x121
23 228 02f9eec8 74f7ac74 KERNELBASE!_KernelBaseBaseDllInitialize+0x309
24 14 02f9eedc 74f7ab44 KERNELBASE!KernelBaseBaseDllInitialize+0x2a
25 10 02f9eeec 774cd556 KERNELBASE!KernelBaseDllInitialize+0x14
26 20 02f9ef0c 7747a1bd ntdll!LdrxCallInitRoutine+0x16
27 4c 02f9ef58 774b0003 ntdll!LdrpCallInitRoutine+0x51
28 88 02f9efe0 774afe86 ntdll!LdrpInitializeNode+0x12f
29 24 02f9f004 774afe9d ntdll!LdrpInitializeGraphRecurse+0x5d
2a 28 02f9f02c 77498f48 ntdll!LdrpInitializeGraphRecurse+0x74
2b 1c 02f9f048 7747c014 ntdll!LdrpPrepareModuleForExecution+0x8b
2c 48 02f9f090 77478757 ntdll!LdrpLoadDllInternal+0x11e
2d 140 02f9f1d0 77477347 ntdll!LdrpLoadDll+0x7e
2e 80 02f9f250 7750aa36 ntdll!LdrLoadDll+0x97
2f 270 02f9f4c0 774b7ba6 ntdll!LdrpInitializeProcess+0x1656
30 58 02f9f518 774b7a71 ntdll!_LdrpInitialize+0xdf
31 c 02f9f524 00000000 ntdll!LdrInitializeThunk+0x11

Q3: Why are you not using PsSetCreateProcessNotifyRoutineEx?
As we are run on WinXP also so using old one. But now when I tried to use “PsSetCreateProcessNotifyRoutineEx” then driver is unable to start/load.
**Is any addition step(s) is/are required for using “PsSetCreateProcessNotifyRoutineEx” ? **

Q1: Do you have big buffers on the stack?
No. We didn’t have big buffers on the stack.
(As I mentioned before, It is working on all windows OS (XP,Vista,Win7,Win8.1,Win10) and 32 and 64 Bits but failed with above error only on
Win10 32bit build 1903.)

Q2: Please provide the output of kf.

0: kd> kF
*** Stack trace for last set context - .thread/.cxr resets it

Memory ChildEBP RetAddr

00 a8d69038 82636bab nt!ExpAcquireResourceSharedLite+0x6e
01 10 a8d69048 82965a64 nt!ExAcquireResourceSharedLite+0x3b
02 f0 a8d69138 8296e364 nt!ObpCreateHandle+0x734
03 70c a8d69844 8296df08 nt!PsOpenProcess+0x454
04 1c a8d69860 8277628b nt!NtOpenProcess+0x2c
05 0 a8d69860 82763bf5 nt!KiSystemServicePostCall
06 88 a8d698e8 86974485 nt!ZwOpenProcess+0x11
07 5c a8d69944 86968038 WdFilter!MpGetProcessById+0x6b
08 64 a8d699a8 86967a5e WdFilter!MpObSendOpenProcessBMNotification+0x37e
09 48 a8d699f0 86967464 WdFilter!MpObHandleOpenProcessCallback+0x2be
0a 8 a8d699f8 8296ed9e WdFilter!MpObPreOperationCallback+0x32
0b 44 a8d69a3c 82965d99 nt!ObpCallPreOperationCallbacks+0xee
0c f0 a8d69b2c 8296e364 nt!ObpCreateHandle+0xa69
0d 70c a8d6a238 8296df08 nt!PsOpenProcess+0x454
0e 1c a8d6a254 8277628b nt!NtOpenProcess+0x2c
0f 0 a8d6a254 82763bf5 nt!KiSystemServicePostCall
10 88 a8d6a2dc a3020d0c nt!ZwOpenProcess+0x11
11 40 a8d6a31c a3021479 MYFilter!GetProcessNameFromId+0x44
12 ca8 a8d6afc4 829ba7f6 MYFilter!MYCreateProcessNotificationRoutine+0x1dd
13 60 a8d6b024 829bf034 nt!PspCallProcessNotifyRoutines+0x1c6
14 70 a8d6b094 829a31f4 nt!PspInsertThread+0x4c4
15 7e4 a8d6b878 8277628b nt!NtCreateUserProcess+0x7c4
16 0 a8d6b878 827644a1 nt!KiSystemServicePostCall
17 a4 a8d6b91c a31a6e59 nt!ZwCreateUserProcess+0x11
18 e4 a8d6ba00 a31a6b87 condrv!CdpCreateProcess+0xe9
19 8c a8d6ba8c a31a728f condrv!CdpLaunchServerProcess+0xf7
1a 1c a8d6baa8 8295c04f condrv!CdpFastIoDeviceControl+0x13f
1b 110 a8d6bbb8 829fadea nt!IopXxxControlFile+0x2df
1c 2c a8d6bbe4 8277628b nt!NtDeviceIoControlFile+0x2a
1d 0 a8d6bbe4 774d1570 nt!KiSystemServicePostCall
1e 02f9e9a4 774cfd3a ntdll!KiFastSystemCallRet
1f 4 02f9e9a8 74fc7e9d ntdll!NtDeviceIoControlFile+0xa
20 40 02f9e9e8 74fc7d22 KERNELBASE!ConsoleLaunchServerProcess+0x54
21 280 02f9ec68 74f7b424 KERNELBASE!ConsoleAllocate+0xcf
22 38 02f9eca0 74f7afa0 KERNELBASE!ConsoleInitialize+0x121
23 228 02f9eec8 74f7ac74 KERNELBASE!_KernelBaseBaseDllInitialize+0x309
24 14 02f9eedc 74f7ab44 KERNELBASE!KernelBaseBaseDllInitialize+0x2a
25 10 02f9eeec 774cd556 KERNELBASE!KernelBaseDllInitialize+0x14
26 20 02f9ef0c 7747a1bd ntdll!LdrxCallInitRoutine+0x16
27 4c 02f9ef58 774b0003 ntdll!LdrpCallInitRoutine+0x51
28 88 02f9efe0 774afe86 ntdll!LdrpInitializeNode+0x12f
29 24 02f9f004 774afe9d ntdll!LdrpInitializeGraphRecurse+0x5d
2a 28 02f9f02c 77498f48 ntdll!LdrpInitializeGraphRecurse+0x74
2b 1c 02f9f048 7747c014 ntdll!LdrpPrepareModuleForExecution+0x8b
2c 48 02f9f090 77478757 ntdll!LdrpLoadDllInternal+0x11e
2d 140 02f9f1d0 77477347 ntdll!LdrpLoadDll+0x7e
2e 80 02f9f250 7750aa36 ntdll!LdrLoadDll+0x97
2f 270 02f9f4c0 774b7ba6 ntdll!LdrpInitializeProcess+0x1656
30 58 02f9f518 774b7a71 ntdll!_LdrpInitialize+0xdf
31 c 02f9f524 00000000 ntdll!LdrInitializeThunk+0x11

Q3: Why are you not using PsSetCreateProcessNotifyRoutineEx?
As we are run on WinXP also so using old one. But now when I tried to use “PsSetCreateProcessNotifyRoutineEx” then driver is unable to start/load.
**Is any addition step(s) is/are required for using “PsSetCreateProcessNotifyRoutineEx” ? **

When used “PsSetCreateProcessNotifyRoutineEx” with LINKER_FLAGS=/INTEGRITYCHECK then driver is able to start/load. But still I am facing the same issue.

====
BOOLEAN
GetProcessNameFromId(
HANDLE hProcessId,
PUNICODE_STRING Path)
{
NTSTATUS Status = STATUS_SUCCESS;
HANDLE handle;
OBJECT_ATTRIBUTES objectAttributes;
CLIENT_ID ClientId;
ULONG cbRet=0;

// Get the full path name of the executable.
InitializeObjectAttributes (&objectAttributes, 0, 0, 0 , 0);

ClientId.UniqueProcess=hProcessId;
ClientId.UniqueThread=0;

Status=ZwOpenProcess(&handle, PROCESS_ALL_ACCESS, &objectAttributes, &ClientId);
if( !NT_SUCCESS(Status) )
	return FALSE;

Status = ZwQueryInformationProcess(
	handle,
	ProcessImageFileName,
	Path,
	Path->MaximumLength,
	&cbRet);

if(!NT_SUCCESS(Status))
{
	ZwClose( handle );
	return FALSE;
}

ZwClose( handle );

return TRUE;

}

What do you have on the stack in MYCreateProcessNotificationRoutine that requires 3,240 bytes of stack? The stack is only 12K on the x86 so that’s a lot.

If you limit that you might still crash due to the recursive nature of the call stack here (note that your ZwOpenProcess is calling into Defender, which is doing its own ZwOpenProcess). I see three solutions:

  1. Reduce your stack utilization in your callback. If the crash goes away you’re living on the edge, but this is a good idea and should be done anyway.
  2. Use KeExpandKernelStackAndCallout to call your GetProcessNameFromId function to ensure that there is sufficient stack before making the ZwOpenProcess call
  3. Avoid using ZwOpenProcess in this callback. For example, if you switch to the Ex version you can use FltGetFileNameInformationUnsafe on the CreateInfo->FileObject parameter to get the name. This might have its own stack utilization problems, but it’s a good way to query the image name in any case

[The MODS write: You know how many copies of your post that starts “I do not have big buffers on the stack” I had to delete? A lot.

Please read this post. Please. Please.

Peter]

@anupyash said:
When used “PsSetCreateProcessNotifyRoutineEx” with LINKER_FLAGS=/INTEGRITYCHECK then driver is able to start/load. But still I am facing the same issue.

====
BOOLEAN
GetProcessNameFromId(
HANDLE hProcessId,
PUNICODE_STRING Path)
{
NTSTATUS Status = STATUS_SUCCESS;
HANDLE handle;
OBJECT_ATTRIBUTES objectAttributes;
CLIENT_ID ClientId;
ULONG cbRet=0;

// Get the full path name of the executable.
InitializeObjectAttributes (&objectAttributes, 0, 0, 0 , 0);

ClientId.UniqueProcess=hProcessId;
ClientId.UniqueThread=0;

Status=ZwOpenProcess(&handle, PROCESS_ALL_ACCESS, &objectAttributes, &ClientId);
if( !NT_SUCCESS(Status) )
return FALSE;

Status = ZwQueryInformationProcess(
handle,
ProcessImageFileName,
Path,
Path->MaximumLength,
&cbRet);

if(!NT_SUCCESS(Status))
{
ZwClose( handle );
return FALSE;
}

ZwClose( handle );

return TRUE;
}

Suggestion (try out), Use local variable (UNICODE_STRING) with ZwQueryInformationProcess and on success copy the path in return buffer.

Note: Call ZwQueryInformationProcess with NULL to get desire required memory size to store path.

@“Scott_Noone_(OSR)” said:
What do you have on the stack in MYCreateProcessNotificationRoutine that requires 3,240 bytes of stack? The stack is only 12K on the x86 so that’s a lot.

If you limit that you might still crash due to the recursive nature of the call stack here (note that your ZwOpenProcess is calling into Defender, which is doing its own ZwOpenProcess). I see three solutions:

  1. Reduce your stack utilization in your callback. If the crash goes away you’re living on the edge, but this is a good idea and should be done anyway.
  2. Use KeExpandKernelStackAndCallout to call your GetProcessNameFromId function to ensure that there is sufficient stack before making the ZwOpenProcess call
  3. Avoid using ZwOpenProcess in this callback. For example, if you switch to the Ex version you can use FltGetFileNameInformationUnsafe on the CreateInfo->FileObject parameter to get the name. This might have its own stack utilization problems, but it’s a good way to query the image name in any case

========
Thank you “Scott_Noone”. Your solution works for me.

@anupyash said:
[The MODS write: You know how many copies of your post that starts “I do not have big buffers on the stack” I had to delete? A lot.

Please read this post. Please. Please.

Peter]

Sorry sir… I will follow the path

Glad you resolved it, which solution did you go with?