void ApcLoadDll(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2);
void ApcLoadDllEnd();
PMDL pMdl = NULL;
void ApcKernelRoutine( IN struct _KAPC *Apc,
IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2 )
{
if (Apc)
ExFreePool(Apc);
if(pMdl)
{
MmUnlockPages(pMdl);
IoFreeMdl (pMdl);
pMdl = NULL;
}
DbgPrint("ApcKernelRoutine called. Memory freed.");
}
VOID AddApcIngectDll(LPSTR DllFullPath, PETHREAD Thread,ULONG pTargetProcess,void *LoadLibraryWAddr)
{
PRKAPC pApc = NULL;
PVOID pMappedAddress = NULL;
ULONG dwSize = 0;
KAPC_STATE ApcState;
int *p=NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if ( MmIsAddressValid((PVOID)Thread) == TRUE)
{
pApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (!pApc)
{
DbgPrint("Failed to allocate memory for the APC structure");
return ;
}
dwSize = 386;//这个长度是我们写的大片的nop
pMdl = IoAllocateMdl (ApcLoadDll, dwSize, FALSE,FALSE,NULL);
if (!pMdl)
{
DbgPrint(" Failed to allocate MDL");
ExFreePool (pApc);
return STATUS_INSUFFICIENT_RESOURCES;
}
__try
{
MmProbeAndLockPages (pMdl,KernelMode,IoWriteAccess);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("Exception during MmProbeAndLockPages");
IoFreeMdl (pMdl);
ExFreePool (pApc);
return STATUS_UNSUCCESSFUL;
}
KeStackAttachProcess((ULONG *)pTargetProcess,&ApcState);//进入目标进程的上下文
pMappedAddress = MmMapLockedPagesSpecifyCache (pMdl,UserMode,MmCached,NULL,FALSE,NormalPagePriority);//把分配好的内存映射进目标进程里面
if (!pMappedAddress)
{
DbgPrint("Cannot map address");
KeUnstackDetachProcess (&ApcState);
IoFreeMdl (pMdl);
ExFreePool (pApc);
return STATUS_UNSUCCESSFUL;
}
else
DbgPrint("UserMode memory at address: 0x%p",pMappedAddress);
wcscpy ((unsigned char*)pMappedAddress + 0x16, DllFullPath);//将dll路径拷贝到目标进程空间
p=(int*)((unsigned char*)pMappedAddress+6);
*p=(int)((unsigned char*)pMappedAddress + 0x16);
p=(int*)((unsigned char*)pMappedAddress+1);
*p=LoadLibraryWAddr;
KeUnstackDetachProcess (&ApcState); //恢复咱原来的上下文
//初始化APC,插APC
KeInitializeApc(pApc,
(PETHREAD)Thread,
OriginalApcEnvironment,
&ApcKernelRoutine,
NULL,
(PKNORMAL_ROUTINE)pMappedAddress,
UserMode,
(PVOID) NULL);
if (!KeInsertQueueApc(pApc,0,NULL,0))
{
DbgPrint("KernelExec -> Failed to insert APC");
MmUnlockPages(pMdl);
IoFreeMdl (pMdl);
ExFreePool (pApc);
return STATUS_UNSUCCESSFUL;
}
else
{
DbgPrint("APC delivered");
}
//使线程处于警告状态,注意不同操作系统的ETHREAD
if(!*(char *)((char *)Thread+0x4a))
{
*(char *)((char *)Thread+0x4a) = TRUE;
}
}
}
//枚举指定进程的线程
NTSTATUS IngectDll(PEPROCESS Process,LPSTR DllFullPath,void *LoadLibraryWAddr)
{
ULONG i;
PETHREAD txtd;
PEPROCESS txps;
NTSTATUS st = STATUS_UNSUCCESSFUL;
for (i=8;i<=65536;i=i+4)
{
st = PsLookupThreadByThreadId(i,&txtd);
if ( NT_SUCCESS(st) )
{
txps=IoThreadToProcess(txtd);
if ( txps == Process )
{
AddApcIngectDll(DllFullPath, txtd,Process,LoadLibraryWAddr);
return STATUS_SUCCESS; //只需要枚举一个线程就够了。因为我们注入dll只需要调用一次
}
}
}
return STATUS_SUCCESS;
}
__declspec(naked) void ApcLoadDll(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
__asm
{
mov eax,0xabcdef //LoadLibraryW的地址这是是需要复制到目标进程空间之后再赋值的
push 0xabcdef //这是是需要复制到目标进程空间之后再赋值的
call eax
jmp end
nop //分配内存
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
end:
ret 0x0c
}
}