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 } }