if(!NT_SUCCESS(PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread,&Thread)))
{
DbgPrint("Error: Unable to reference the target thread.");
ObDereferenceObject(Process); // Dereference the target process
ExFreePool(buffer); // Free the allocated memory
return FALSE;
}
DbgPrint("ETHREAD address: %#x",Thread);
ExFreePool(buffer); // Free the allocated memory
KeAttachProcess(Process); // Attach to target process's address space
mem=NULL;
size=4096;
// Allocate memory in the target process
if(!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,0,&size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE)))
{
DbgPrint("Error: Unable to allocate memory in the target process.");
KeDetachProcess(); // Detach from target process's address space
ObDereferenceObject(Process); // Dereference the target process
ObDereferenceObject(Thread); // Dereference the target thread
return FALSE;
}
DbgPrint("Memory allocated at %#x",mem);
mem->LdrLoadDll=LdrLoadDll; // Write the address of LdrLoadDll to target process
wcscpy(mem->Buffer,InjectInfo->DllName); // Write the DLL name to target process
RtlInitUnicodeString(&mem->DllName,mem->Buffer); // Initialize the UNICODE_STRING structure
ApcState=(PKAPC_STATE)((PUCHAR)Thread+ApcStateOffset); // Calculate the address of the ApcState structure
ApcState->UserApcPending=TRUE; // Force the target thread to execute APC
memcpy((PKINJECT)(mem+1),InjectDllApc,(ULONG)KernelRoutine-(ULONG)InjectDllApc); // Copy the APC code to target process
DbgPrint("APC code address: %#x",(PKINJECT)(mem+1));
apc=(PKAPC)ExAllocatePool(NonPagedPool,sizeof(KAPC)); // Allocate the APC object
if(!apc)
{
DbgPrint("Error: Unable to allocate the APC object.");
size=0;
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory
KeDetachProcess(); // Detach from target process's address space
ObDereferenceObject(Process); // Dereference the target process
ObDereferenceObject(Thread); // Dereference the target thread
return FALSE;
}
KeInitializeApc(apc,Thread,OriginalApcEnvironment,KernelRoutine,NULL,(PKNORMAL_ROUTINE)((PKINJECT)mem+1),UserMode,mem); // Initialize the APC
DbgPrint("Inserting APC to target thread");
// Insert the APC to the target thread
if(!KeInsertQueueApc(apc,NULL,NULL,IO_NO_INCREMENT))
{
DbgPrint("Error: Unable to insert APC to target thread.");
size=0;
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory
KeDetachProcess(); // Detach from target process's address space
ObDereferenceObject(Process); // Dereference the target process
ObDereferenceObject(Thread); // Dereference the target thread
ExFreePool(apc); // Free the APC object
return FALSE;
}
delay.QuadPart=-100*10000;
while(!mem->Executed)
{
KeDelayExecutionThread(KernelMode,FALSE,&delay); // Wait for the injection to complete
}
if(!mem->DllBase)
{
DbgPrint("Error: Unable to inject DLL into target process.");
size=0;
DbgPrint("DLL injected at %#x",mem->DllBase);
size=0;
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE); // Free the allocated memory
KeDetachProcess(); // Detach from target process's address space
ObDereferenceObject(Process); // Dereference the target process
ObDereferenceObject(Thread); // Dereference the target thread