内核中通过给线程插apc注入dll

2019-11-18 22:18:05 浏览数 (1)

代码语言:javascript复制
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 //分配内存
end:
		ret 0x0c
	}
}
dll

0 人点赞