[原创]今天写了个apc注入dll代码,可以当工具使用
ring0和ring3都有,像我这样菜鸟写这么个代码真累啊
typedef struct _INJECT_INFO
{
HANDLE ProcessId;
wchar_t DllName[1024];
}INJECT_INFO,*PINJECT_INFO;
BOOLEAN InjectDll(PINJECT_INFO InjectInfo)
{
PEPROCESS Process;
PETHREAD Thread;
PKINJECT mem;
ULONG size;
PKAPC_STATE ApcState;
PKAPC apc;
PVOID buffer;
PSYSTEM_PROCESS_INFO pSpi;
LARGE_INTEGER delay;
buffer=ExAllocatePool(NonPagedPool,1024*1024); // Allocate memory for the system information
if(!buffer)
{
DbgPrint("Error: Unable to allocate memory for the process thread list.");
return FALSE;
}
// Get the process thread list
if(!NT_SUCCESS(ZwQuerySystemInformation(5,buffer,1024*1024,NULL)))
{
DbgPrint("Error: Unable to query process thread list.");
ExFreePool(buffer);
return FALSE;
}
pSpi=(PSYSTEM_PROCESS_INFO)buffer;
// Find a target thread
while(pSpi->NextEntryOffset)
{
if(pSpi->UniqueProcessId==InjectInfo->ProcessId)
{
DbgPrint("Target thread found. TID: %d",pSpi->Threads[0].ClientId.UniqueThread);
break;
}
pSpi=(PSYSTEM_PROCESS_INFO)((PUCHAR)pSpi+pSpi->NextEntryOffset);
}
// Reference the target process
if(!NT_SUCCESS(PsLookupProcessByProcessId(InjectInfo->ProcessId,&Process)))
{
DbgPrint("Error: Unable to reference the target process.");
ExFreePool(buffer);
return FALSE;
}
DbgPrint("Process name: %s",PsGetProcessImageFileName(Process));
DbgPrint("EPROCESS address: %#x",Process);
// Reference the target thread
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;
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&mem,&size,MEM_RELEASE);
KeDetachProcess();
ObDereferenceObject(Process);
ObDereferenceObject(Thread);
return FALSE;
}
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
return TRUE;
}
