diff --git a/src/injlib/injlib.c b/src/injlib/injlib.c index 3281b9d..218e476 100644 --- a/src/injlib/injlib.c +++ b/src/injlib/injlib.c @@ -212,6 +212,12 @@ InjpInjectApcKernelRoutine( _Inout_ PVOID* SystemArgument2 ); +VOID +NTAPI +InjpInjectApcRundownRoutine( + _In_ PKAPC Apc +); + // // reparse.c // @@ -381,6 +387,9 @@ UCHAR InjpThunkARM64[] = { // ////////////////////////////////////////////////////////////////////////// LIST_ENTRY InjInfoListHead; +FAST_MUTEX InjInfoMutex; + +EX_RUNDOWN_REF ApcRundownProtection; INJ_METHOD InjMethod; @@ -581,11 +590,25 @@ InjpQueueApc( PsGetCurrentThread(), // Thread OriginalApcEnvironment, // Environment &InjpInjectApcKernelRoutine, // KernelRoutine - NULL, // RundownRoutine + &InjpInjectApcRundownRoutine, // RundownRoutine NormalRoutine, // NormalRoutine ApcMode, // ApcMode NormalContext); // NormalContext + + // + // Acquire rundown protection before inserting new + // KernelMode APC and release it after injecting + // + + if (ApcMode == KernelMode) { + BOOLEAN acquired = ExAcquireRundownProtection(&ApcRundownProtection); + if (!acquired) { + ExFreePoolWithTag(Apc, INJ_MEMORY_TAG); + return STATUS_UNSUCCESSFUL; + } + } + BOOLEAN Inserted = KeInsertQueueApc(Apc, // Apc SystemArgument1, // SystemArgument1 SystemArgument2, // SystemArgument2 @@ -594,6 +617,11 @@ InjpQueueApc( if (!Inserted) { ExFreePoolWithTag(Apc, INJ_MEMORY_TAG); + + if (ApcMode == KernelMode) { + ExReleaseRundownProtection(&ApcRundownProtection); + } + return STATUS_UNSUCCESSFUL; } @@ -615,6 +643,15 @@ InjpInjectApcNormalRoutine( InjInject(InjectionInfo); } +VOID +NTAPI +InjpInjectApcRundownRoutine( + _In_ PKAPC Apc +) { + ExFreePoolWithTag(Apc, INJ_MEMORY_TAG); + ExReleaseRundownProtection(&ApcRundownProtection); +} + VOID NTAPI InjpInjectApcKernelRoutine( @@ -879,6 +916,13 @@ InjInitialize( // InitializeListHead(&InjInfoListHead); + ExInitializeFastMutex(&InjInfoMutex); + + // + // Initialize APC rundown protection + // + + ExInitializeRundownProtection(&ApcRundownProtection); ULONG Flags = RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING; @@ -959,6 +1003,7 @@ InjDestroy( // // Release memory of all injection-info entries. // + ExAcquireFastMutex(&InjInfoMutex); PLIST_ENTRY NextEntry = InjInfoListHead.Flink; @@ -980,6 +1025,14 @@ InjDestroy( { RtlFreeUnicodeString(&InjDllPath[Architecture]); } + + ExReleaseFastMutex(&InjInfoMutex); + + // + // Prevent unloading while there are APCs in the queue + // + + ExWaitForRundownProtectionRelease(&ApcRundownProtection); } NTSTATUS @@ -991,6 +1044,8 @@ InjCreateInjectionInfo( { PINJ_INJECTION_INFO CapturedInjectionInfo; + ExAcquireFastMutex(&InjInfoMutex); + if (InjectionInfo && *InjectionInfo) { CapturedInjectionInfo = *InjectionInfo; @@ -1003,6 +1058,7 @@ InjCreateInjectionInfo( if (!CapturedInjectionInfo) { + ExReleaseFastMutex(&InjInfoMutex); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1020,6 +1076,8 @@ InjCreateInjectionInfo( InsertTailList(&InjInfoListHead, &CapturedInjectionInfo->ListEntry); + + ExReleaseFastMutex(&InjInfoMutex); return STATUS_SUCCESS; } @@ -1059,6 +1117,8 @@ InjFindInjectionInfo( _In_ HANDLE ProcessId ) { + ExAcquireFastMutex(&InjInfoMutex); + PLIST_ENTRY NextEntry = InjInfoListHead.Flink; while (NextEntry != &InjInfoListHead) @@ -1069,12 +1129,15 @@ InjFindInjectionInfo( if (InjectionInfo->ProcessId == ProcessId) { + ExReleaseFastMutex(&InjInfoMutex); return InjectionInfo; } NextEntry = NextEntry->Flink; } + + ExReleaseFastMutex(&InjInfoMutex); return NULL; } @@ -1255,6 +1318,7 @@ InjInject( #endif ZwClose(SectionHandle); + ExReleaseRundownProtection(&ApcRundownProtection); if (NT_SUCCESS(Status) && InjectionInfo->ForceUserApc) {